use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class DMLModStatementNode method parseAndBindGenerationClauses.
/**
* Parse and bind the generating expressions of computed columns.
*
* @param dataDictionary metadata
* @param targetTableDescriptor metadata for the table that has the generated columns
* @param sourceRCL the tuple stream which drives the INSERT or UPDATE
* @param targetRCL the row in the table that's being INSERTed or UPDATEd
* @param forUpdate true if this is an UPDATE. false otherwise.
* @param updateResultSet more information on the tuple stream driving the UPDATE
*/
void parseAndBindGenerationClauses(DataDictionary dataDictionary, TableDescriptor targetTableDescriptor, ResultColumnList sourceRCL, ResultColumnList targetRCL, boolean forUpdate, ResultSetNode updateResultSet) throws StandardException {
CompilerContext compilerContext = getCompilerContext();
int count = targetRCL.size();
for (int i = 0; i < count; i++) {
ResultColumn rc = targetRCL.elementAt(i);
//
if (forUpdate && !rc.updated()) {
continue;
}
if (rc.hasGenerationClause()) {
ColumnDescriptor colDesc = rc.getTableColumnDescriptor();
DataTypeDescriptor dtd = colDesc.getType();
DefaultInfo di = colDesc.getDefaultInfo();
ValueNode generationClause = parseGenerationClause(di.getDefaultText(), targetTableDescriptor);
// insert CAST in case column data type is not same as the
// resolved type of the generation clause
generationClause = new CastNode(generationClause, dtd, getContextManager());
// Assignment semantics of implicit cast here:
// Section 9.2 (Store assignment). There, General Rule
// 2.b.v.2 says that the database should raise an exception
// if truncation occurs when stuffing a string value into a
// VARCHAR, so make sure CAST doesn't issue warning only.
((CastNode) generationClause).setAssignmentSemantics();
//
// Unqualified function references should resolve to the
// current schema at the time that the table was
// created/altered. See DERBY-3945.
//
compilerContext.pushCompilationSchema(getSchemaDescriptor(di.getOriginalCurrentSchema(), false));
try {
bindRowScopedExpression(getOptimizerFactory(), getContextManager(), targetTableDescriptor, sourceRCL, generationClause);
} finally {
compilerContext.popCompilationSchema();
}
ResultColumn newRC = new ResultColumn(generationClause.getTypeServices(), generationClause, getContextManager());
// replace the result column in place
// column ids are 1-based
newRC.setVirtualColumnId(i + 1);
newRC.setColumnDescriptor(targetTableDescriptor, colDesc);
targetRCL.setElementAt(newRC, i);
// generate correctly if they reference the generated column
if (forUpdate) {
for (int j = 0; j < sourceRCL.size(); j++) {
if (rc == sourceRCL.elementAt(j)) {
newRC.setName(rc.getName());
newRC.setResultSetNumber(updateResultSet.getResultSetNumber());
sourceRCL.setElementAt(newRC, j);
}
}
// end of loop through sourceRCL
}
// end if this is an update statement
}
// end if this is a generated column
}
// end of loop through targetRCL
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class DMLModStatementNode method generateFKInfo.
/**
* Generate the FKInfo structures used during code generation.
* For each constraint that isn't a check constraint, add another
* one of these FKInfo structures and then package them up into
* a single array.
*
* @param cdl The constraint descriptor list
* @param dd The DataDictionary
* @param td The TableDescriptor
* @param readColsBitSet columns read
*
* @exception StandardException Thrown on failure
*/
private void generateFKInfo(ConstraintDescriptorList cdl, DataDictionary dd, TableDescriptor td, FormatableBitSet readColsBitSet) throws StandardException {
ArrayList<FKInfo> fkList = new ArrayList<FKInfo>();
int type;
UUID[] uuids;
long[] conglomNumbers;
String[] fkNames;
ConstraintDescriptorList fkcdl;
ReferencedKeyConstraintDescriptor refcd;
boolean[] isSelfReferencingFK;
ConstraintDescriptorList activeList = dd.getActiveConstraintDescriptors(cdl);
int[] rowMap = getRowMap(readColsBitSet, td);
int[] raRules;
boolean[] deferrable;
UUID[] fkIds;
ArrayList<String> refSchemaNames = new ArrayList<String>(1);
ArrayList<String> refTableNames = new ArrayList<String>(1);
ArrayList<Long> refIndexConglomNum = new ArrayList<Long>(1);
ArrayList<Integer> refActions = new ArrayList<Integer>(1);
ArrayList<ColumnDescriptorList> refColDescriptors = new ArrayList<ColumnDescriptorList>(1);
ArrayList<int[]> fkColMap = new ArrayList<int[]>(1);
int activeSize = activeList.size();
for (int index = 0; index < activeSize; index++) {
ConstraintDescriptor cd = activeList.elementAt(index);
if (cd instanceof ForeignKeyConstraintDescriptor) {
/*
** We are saving information for checking the
** primary/unique key that is referenced by this
** foreign key, so type is FOREIGN KEY.
*/
type = FKInfo.FOREIGN_KEY;
refcd = ((ForeignKeyConstraintDescriptor) cd).getReferencedConstraint();
uuids = new UUID[1];
deferrable = new boolean[1];
fkIds = new UUID[1];
conglomNumbers = new long[1];
fkNames = new String[1];
isSelfReferencingFK = new boolean[1];
raRules = new int[1];
fkSetupArrays(dd, (ForeignKeyConstraintDescriptor) cd, 0, uuids, conglomNumbers, fkNames, isSelfReferencingFK, raRules, deferrable, fkIds);
// oops, get the right constraint name -- for error
// handling we want the FK name, not refcd name
fkNames[0] = cd.getConstraintName();
} else if (cd instanceof ReferencedKeyConstraintDescriptor) {
refcd = (ReferencedKeyConstraintDescriptor) cd;
/*
** We are saving information for checking the
** foreign key(s) that is dependent on this referenced
** key, so type is REFERENCED KEY.
*/
type = FKInfo.REFERENCED_KEY;
fkcdl = dd.getActiveConstraintDescriptors(((ReferencedKeyConstraintDescriptor) cd).getForeignKeyConstraints(ConstraintDescriptor.ENABLED));
int size = fkcdl.size();
if (size == 0) {
continue;
}
uuids = new UUID[size];
deferrable = new boolean[size];
fkIds = new UUID[size];
fkNames = new String[size];
conglomNumbers = new long[size];
isSelfReferencingFK = new boolean[size];
raRules = new int[size];
TableDescriptor fktd;
ColumnDescriptorList coldl;
int[] refColumns;
ColumnDescriptor cold;
int[] colArray = remapReferencedColumns(cd, rowMap);
for (int inner = 0; inner < size; inner++) {
ForeignKeyConstraintDescriptor fkcd = (ForeignKeyConstraintDescriptor) fkcdl.elementAt(inner);
fkSetupArrays(dd, fkcd, inner, uuids, conglomNumbers, fkNames, isSelfReferencingFK, raRules, deferrable, fkIds);
if ((raRules[inner] == StatementType.RA_CASCADE) || (raRules[inner] == StatementType.RA_SETNULL)) {
// find the referencing table Name
fktd = fkcd.getTableDescriptor();
refSchemaNames.add(fktd.getSchemaName());
refTableNames.add(fktd.getName());
refActions.add(Integer.valueOf(raRules[inner]));
// find the referencing column name required for update null.
refColumns = fkcd.getReferencedColumns();
coldl = fktd.getColumnDescriptorList();
ColumnDescriptorList releventColDes = new ColumnDescriptorList();
for (int i = 0; i < refColumns.length; i++) {
cold = coldl.elementAt(refColumns[i] - 1);
releventColDes.add(cold);
}
refColDescriptors.add(releventColDes);
refIndexConglomNum.add(Long.valueOf(conglomNumbers[inner]));
fkColMap.add(colArray);
}
}
} else {
continue;
}
final TableDescriptor pktd = refcd.getTableDescriptor();
final UUID pkIndexId = refcd.getIndexId();
final ConglomerateDescriptor pkIndexConglom = pktd.getConglomerateDescriptor(pkIndexId);
final TableDescriptor refTd = cd.getTableDescriptor();
fkList.add(new FKInfo(// foreign key names
fkNames, cd.getSchemaDescriptor().getSchemaName(), // table being modified
refTd.getName(), // INSERT|UPDATE|DELETE
statementType, // FOREIGN_KEY|REFERENCED_KEY
type, // referenced backing index uuid
pkIndexId, pkIndexConglom.getConglomerateNumber(), // referenced backing index conglom
refcd.getUUID(), // referenced constraint is
refcd.deferrable(), // fk backing index uuids
uuids, // fk backing index congloms
conglomNumbers, // is self ref array of bool
isSelfReferencingFK, remapReferencedColumns(cd, rowMap), // columns referenced by key
dd.getRowLocationTemplate(getLanguageConnectionContext(), refTd), // referential action rules
raRules, // deferrable flags
deferrable, // UUID of fks
fkIds));
}
// Now convert the list into an array.
if (!fkList.isEmpty()) {
fkInfo = fkList.toArray(new FKInfo[fkList.size()]);
}
// Convert the ref action info lists to arrays.
int size = refActions.size();
if (size > 0) {
fkTableNames = new String[size];
fkSchemaNames = new String[size];
fkRefActions = new int[size];
fkColDescriptors = new ColumnDescriptorList[size];
fkIndexConglomNumbers = new long[size];
fkColArrays = new int[size][];
for (int i = 0; i < size; i++) {
fkTableNames[i] = refTableNames.get(i);
fkSchemaNames[i] = refSchemaNames.get(i);
fkRefActions[i] = (refActions.get(i)).intValue();
fkColDescriptors[i] = refColDescriptors.get(i);
fkIndexConglomNumbers[i] = (refIndexConglomNum.get(i)).longValue();
fkColArrays[i] = (fkColMap.get(i));
}
}
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor 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.ColumnDescriptor in project derby by apache.
the class FromBaseTable method addColsToList.
/**
* Augment the RCL to include the columns in the FormatableBitSet.
* If the column is already there, don't add it twice.
* Column is added as a ResultColumn pointing to a
* ColumnReference.
*
* @param inputRcl The original list
* @param colsWeWant bit set of cols we want
*
* @return ResultColumnList the rcl
*
* @exception StandardException Thrown on error
*/
ResultColumnList addColsToList(ResultColumnList inputRcl, FormatableBitSet colsWeWant) throws StandardException {
ResultColumn resultColumn;
TableName exposedName;
/* Cache exposed name for this table.
* The exposed name becomes the qualifier for each column
* in the expanded list.
*/
exposedName = getExposedTableName();
/* Add all of the columns in the table */
ResultColumnList newRcl = new ResultColumnList((getContextManager()));
ColumnDescriptorList cdl = tableDescriptor.getColumnDescriptorList();
int cdlSize = cdl.size();
for (int index = 0; index < cdlSize; index++) {
/* Build a ResultColumn/BaseColumnNode pair for the column */
ColumnDescriptor cd = cdl.elementAt(index);
int position = cd.getPosition();
if (!colsWeWant.get(position)) {
continue;
}
if ((resultColumn = inputRcl.getResultColumn(position)) == null) {
ColumnReference cr = new ColumnReference(cd.getColumnName(), exposedName, getContextManager());
if ((getMergeTableID() != ColumnReference.MERGE_UNKNOWN)) {
cr.setMergeTableID(getMergeTableID());
}
resultColumn = new ResultColumn(cd, cr, getContextManager());
}
/* Build the ResultColumnList to return */
newRcl.addResultColumn(resultColumn);
}
return newRcl;
}
use of org.apache.derby.iapi.sql.dictionary.ColumnDescriptor in project derby by apache.
the class DefaultNode method bindExpression.
/**
* Bind this expression. This means binding the sub-expressions,
* as well as figuring out what the return type is for this expression.
* In this case, there are no sub-expressions, and the return type
* is already known, so this is just a stub.
*
* @param fromList The FROM list for the query this
* expression is in, for binding columns.
* @param subqueryList The subquery list being built as we find SubqueryNodes
* @param aggregates The aggregate list being built as we find AggregateNodes
*
* @return The new top of the expression tree.
*
* @exception StandardException Thrown on failure
*/
@Override
ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
ColumnDescriptor cd;
TableDescriptor td;
if (SanityManager.DEBUG) {
SanityManager.ASSERT(fromList.size() != 0, "fromList expected to be non-empty");
if (!(fromList.elementAt(0) instanceof FromBaseTable)) {
SanityManager.THROWASSERT("fromList.elementAt(0) expected to be instanceof FromBaseTable, not " + fromList.elementAt(0).getClass().getName());
}
}
// Get the TableDescriptor for the target table
td = ((FromBaseTable) fromList.elementAt(0)).getTableDescriptor();
// Get the ColumnDescriptor for the column
cd = td.getColumnDescriptor(columnName);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(cd != null, "cd expected to be non-null");
}
/* If we have the default text, then parse and bind it and
* return the tree.
*/
DefaultInfoImpl defaultInfo = (DefaultInfoImpl) cd.getDefaultInfo();
if (defaultInfo != null) {
String defaultTxt = defaultInfo.getDefaultText();
ValueNode defaultTre = parseDefault(defaultTxt, getLanguageConnectionContext(), getCompilerContext());
/* Query is dependent on the DefaultDescriptor */
DefaultDescriptor defaultDescriptor = cd.getDefaultDescriptor(getDataDictionary());
getCompilerContext().createDependency(defaultDescriptor);
return defaultTre.bindExpression(fromList, subqueryList, aggregates);
} else {
// Default is null
return new UntypedNullConstantNode(getContextManager());
}
}
Aggregations