use of org.apache.derby.iapi.sql.dictionary.TableDescriptor in project derby by apache.
the class MatchingClauseNode method buildThenColumnsForInsert.
/**
* <p>
* Construct the row in the temporary table which drives an INSERT action.
* Unlike a DELETE, whose temporary row is just a list of copied columns, the
* temporary row for INSERT may contain complex expressions which must
* be code-generated later on.
* </p>
*/
private void buildThenColumnsForInsert(FromList fullFromList, FromTable targetTable, ResultColumnList fullRow, ResultColumnList insertColumns, ResultColumnList insertValues) throws StandardException {
//
// Don't add USAGE privilege on user-defined types just because we're
// building the THEN columns.
//
boolean wasSkippingTypePrivileges = getCompilerContext().skipTypePrivileges(true);
TableDescriptor td = targetTable.getTableDescriptor();
_thenColumns = fullRow.copyListAndObjects();
//
for (int i = 0; i < _thenColumns.size(); i++) {
ResultColumn origRC = _thenColumns.elementAt(i);
String columnName = origRC.getName();
ColumnDescriptor cd = td.getColumnDescriptor(columnName);
boolean changed = false;
//
if (!origRC.isAutoincrement() && (origRC.getExpression() instanceof VirtualColumnNode)) {
origRC.setExpression(new UntypedNullConstantNode(getContextManager()));
}
if (cd.hasGenerationClause()) {
origRC.setExpression(new UntypedNullConstantNode(getContextManager()));
continue;
}
for (int ic = 0; ic < insertColumns.size(); ic++) {
ResultColumn icRC = insertColumns.elementAt(ic);
if (columnName.equals(icRC.getName())) {
ResultColumn newRC = null;
// replace DEFAULT for a generated or identity column
ResultColumn valueRC = insertValues.elementAt(ic);
if (valueRC.wasDefaultColumn() || (valueRC.getExpression() instanceof UntypedNullConstantNode)) {
if (!cd.isAutoincrement()) {
//
// Eliminate column references under identity columns. They
// will mess up the code generation.
//
ValueNode expr = origRC.getExpression();
if (expr instanceof ColumnReference) {
origRC.setExpression(new UntypedNullConstantNode(getContextManager()));
}
continue;
}
newRC = makeAutoGenRC(targetTable, origRC, i + 1);
} else {
newRC = valueRC.cloneMe();
newRC.setType(origRC.getTypeServices());
}
newRC.setVirtualColumnId(origRC.getVirtualColumnId());
_thenColumns.setElementAt(newRC, i);
changed = true;
break;
}
}
// plug in defaults if we haven't done so already
if (!changed) {
DefaultInfoImpl defaultInfo = (DefaultInfoImpl) cd.getDefaultInfo();
if ((defaultInfo != null) && !defaultInfo.isGeneratedColumn() && !cd.isAutoincrement()) {
_thenColumns.setDefault(origRC, cd, defaultInfo);
changed = true;
}
}
// set the result column name correctly for buildThenColumnSignature()
ResultColumn finalRC = _thenColumns.elementAt(i);
finalRC.setName(cd.getColumnName());
}
// end loop through _thenColumns
getCompilerContext().skipTypePrivileges(wasSkippingTypePrivileges);
}
use of org.apache.derby.iapi.sql.dictionary.TableDescriptor in project derby by apache.
the class MatchingClauseNode method buildThenColumnsForUpdate.
/**
* <p>
* Construct the row in the temporary table which drives an UPDATE action.
* Unlike a DELETE, whose temporary row is just a list of copied columns, the
* temporary row for UPDATE may contain complex expressions which must
* be code-generated later on.
* </p>
*/
private void buildThenColumnsForUpdate(FromList fullFromList, FromTable targetTable, ResultColumnList fullRow, ResultColumnList beforeRow, ResultColumnList afterValues) throws StandardException {
TableDescriptor td = targetTable.getTableDescriptor();
HashSet<String> changedColumns = getChangedColumnNames();
HashSet<String> changedGeneratedColumns = getChangedGeneratedColumnNames(td, changedColumns);
_thenColumns = fullRow.copyListAndObjects();
//
for (int i = 0; i < _thenColumns.size(); i++) {
ResultColumn origRC = _thenColumns.elementAt(i);
boolean isAfterColumn = (i >= beforeRow.size());
// skip the final RowLocation column of an UPDATE
boolean isRowLocation = isRowLocation(origRC);
ValueNode origExpr = origRC.getExpression();
if (isRowLocation) {
continue;
}
String columnName = origRC.getName();
ColumnDescriptor cd = td.getColumnDescriptor(columnName);
boolean changed = false;
//
if (cd.isAutoincrement() && (origRC.getExpression() instanceof NumericConstantNode)) {
DataValueDescriptor numericValue = ((NumericConstantNode) origRC.getExpression()).getValue();
if (numericValue == null) {
ResultColumn newRC = makeAutoGenRC(targetTable, origRC, i + 1);
newRC.setVirtualColumnId(origRC.getVirtualColumnId());
_thenColumns.setElementAt(newRC, i);
continue;
}
}
//
if (!origRC.isAutoincrement() && (origRC.getExpression() instanceof VirtualColumnNode)) {
origRC.setExpression(new UntypedNullConstantNode(getContextManager()));
}
//
if (cd.hasGenerationClause()) {
if (isAfterColumn && changedGeneratedColumns.contains(columnName)) {
// Set the expression to something that won't choke ResultColumnList.generateEvaluatedRow().
// The value will be a Java null at execution time, which will cause the value
// to be re-generated.
origRC.setExpression(new UntypedNullConstantNode(getContextManager()));
} else {
ColumnReference cr = new ColumnReference(columnName, targetTable.getTableName(), getContextManager());
origRC.setExpression(cr);
// remove the column descriptor in order to turn off hasGenerationClause()
origRC.setColumnDescriptor(null, null);
}
continue;
}
if (isAfterColumn) {
for (int ic = 0; ic < beforeRow.size(); ic++) {
ResultColumn icRC = beforeRow.elementAt(ic);
if (columnName.equals(icRC.getName())) {
ResultColumn newRC = null;
// replace DEFAULT for a generated or identity column
ResultColumn valueRC = afterValues.elementAt(ic);
if (valueRC.wasDefaultColumn() || (valueRC.getExpression() instanceof UntypedNullConstantNode)) {
if (!cd.isAutoincrement()) {
//
// Eliminate column references under identity columns. They
// will mess up the code generation.
//
ValueNode expr = origRC.getExpression();
if (expr instanceof ColumnReference) {
origRC.setExpression(new UntypedNullConstantNode(getContextManager()));
}
continue;
}
newRC = makeAutoGenRC(targetTable, origRC, i + 1);
} else {
newRC = valueRC.cloneMe();
newRC.setType(origRC.getTypeServices());
}
newRC.setVirtualColumnId(origRC.getVirtualColumnId());
_thenColumns.setElementAt(newRC, i);
changed = true;
break;
}
}
}
// plug in defaults if we haven't done so already
if (!changed) {
DefaultInfoImpl defaultInfo = (DefaultInfoImpl) cd.getDefaultInfo();
if ((defaultInfo != null) && !defaultInfo.isGeneratedColumn() && !cd.isAutoincrement()) {
_thenColumns.setDefault(origRC, cd, defaultInfo);
changed = true;
}
}
// set the result column name correctly for buildThenColumnSignature()
ResultColumn finalRC = _thenColumns.elementAt(i);
finalRC.setName(cd.getColumnName());
//
// Turn off the autogenerated bit for identity columns so that
// ResultColumnList.generateEvaluatedRow() doesn't try to compile
// code to generate values for the before images in UPDATE rows.
// This logic will probably need to be revisited as part of fixing derby-6414.
//
finalRC.resetAutoincrementGenerated();
}
// end loop through _thenColumns
}
use of org.apache.derby.iapi.sql.dictionary.TableDescriptor in project derby by apache.
the class MergeNode method targetIsBaseTable.
/**
* Return true if the target table is a base table
*/
private boolean targetIsBaseTable(FromBaseTable targetTable) throws StandardException {
FromBaseTable fbt = targetTable;
TableDescriptor desc = fbt.getTableDescriptor();
if (desc == null) {
return false;
}
switch(desc.getTableType()) {
case TableDescriptor.BASE_TABLE_TYPE:
case TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE:
return true;
default:
return false;
}
}
use of org.apache.derby.iapi.sql.dictionary.TableDescriptor in project derby by apache.
the class CurrentOfNode method bindNonVTITables.
//
// FromTable interface
//
/**
* Binding this FromTable means finding the prepared statement
* for the cursor and creating the result columns (the columns
* updatable on that cursor).
*
* We expect someone else to verify that the target table
* of the positioned update or delete is the table under this cursor.
*
* @param dataDictionary The DataDictionary to use for binding
* @param fromListParam FromList to use/append to.
*
* @return ResultSetNode Returns this.
*
* @exception StandardException Thrown on error
*/
@Override
ResultSetNode bindNonVTITables(DataDictionary dataDictionary, FromList fromListParam) throws StandardException {
// verify that the cursor exists
preStmt = getCursorStatement();
if (preStmt == null) {
throw StandardException.newException(SQLState.LANG_CURSOR_NOT_FOUND, cursorName);
}
preStmt.rePrepare(getLanguageConnectionContext());
// for checking that the right columns are updatable)
if (preStmt.getUpdateMode() != CursorNode.UPDATE) {
String printableString = (cursorName == null) ? "" : cursorName;
throw StandardException.newException(SQLState.LANG_CURSOR_NOT_UPDATABLE, printableString);
}
ExecCursorTableReference refTab = preStmt.getTargetTable();
String schemaName = refTab.getSchemaName();
exposedTableName = makeTableName(null, refTab.getExposedName());
baseTableName = makeTableName(schemaName, refTab.getBaseName());
SchemaDescriptor tableSchema = getSchemaDescriptor(refTab.getSchemaName());
/*
** This will only happen when we are binding against a publication
** dictionary w/o the schema we are interested in.
*/
if (tableSchema == null) {
throw StandardException.newException(SQLState.LANG_SCHEMA_DOES_NOT_EXIST, refTab.getSchemaName());
}
/* Create dependency on target table, in case table not named in
* positioned update/delete. Make sure we find the table descriptor,
* we may fail to find it if we are binding a publication.
*/
TableDescriptor td = getTableDescriptor(refTab.getBaseName(), tableSchema);
if (td == null) {
throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND, refTab.getBaseName());
}
/*
** Add all the result columns from the target table.
** For now, all updatable cursors have all columns
** from the target table. In the future, we should
** relax this so that the cursor may do a partial
** read and then the current of should make sure that
** it can go to the base table to get all of the
** columns needed by the referencing positioned
** DML. In the future, we'll probably need to get
** the result columns from preparedStatement and
** turn them into an RCL that we can run with.
*/
setResultColumns(new ResultColumnList(getContextManager()));
ColumnDescriptorList cdl = td.getColumnDescriptorList();
int cdlSize = cdl.size();
for (int index = 0; index < cdlSize; index++) {
/* Build a ResultColumn/BaseColumnNode pair for the column */
ColumnDescriptor colDesc = cdl.elementAt(index);
BaseColumnNode bcn = new BaseColumnNode(colDesc.getColumnName(), exposedTableName, colDesc.getType(), getContextManager());
ResultColumn rc = new ResultColumn(colDesc, bcn, getContextManager());
/* Build the ResultColumnList to return */
getResultColumns().addResultColumn(rc);
}
/* Assign the tableNumber */
if (// allow re-bind, in which case use old number
tableNumber == -1)
tableNumber = getCompilerContext().getNextTableNumber();
return this;
}
use of org.apache.derby.iapi.sql.dictionary.TableDescriptor in project derby by apache.
the class CursorNode method bindUpdateColumns.
/**
* Bind the update columns by their names to the target table
* of the cursor specification.
* Doesn't check for duplicates in the list, although it could...
* REVISIT: If the list is empty, should it expand it out? at present,
* it leaves it empty.
*
* @param targetTable The underlying target table
*
* @exception StandardException Thrown on error
*/
private void bindUpdateColumns(FromTable targetTable) throws StandardException {
int size = updatableColumns.size();
TableDescriptor tableDescriptor;
String columnName;
ResultColumnList rcl = resultSet.getResultColumns();
for (int index = 0; index < size; index++) {
columnName = updatableColumns.get(index);
tableDescriptor = targetTable.getTableDescriptor();
if (tableDescriptor.getColumnDescriptor(columnName) == null) {
throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND, columnName);
}
for (ResultColumn rc : rcl) {
// Look through each column in the resultset for cursor.
if (rc.getSourceTableName() == null) {
// a derived column in the select list.
continue;
}
if (rc.getExpression() != null && rc.getExpression().getColumnName().equals(columnName) && !rc.getName().equals(columnName)) {
throw StandardException.newException(SQLState.LANG_CORRELATION_NAME_FOR_UPDATABLE_COLUMN_DISALLOWED_IN_CURSOR, columnName);
}
}
}
}
Aggregations