use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class QueryTreeNode method resolveTableToSynonym.
/**
* Resolve table/view reference to a synonym. May have to follow a synonym chain.
*
* @param tabName to match for a synonym
*
* @return Synonym TableName if a match is found, NULL otherwise.
*
* @exception StandardException Thrown on error
*/
TableName resolveTableToSynonym(TableName tabName) throws StandardException {
DataDictionary dd = getDataDictionary();
String nextSynonymTable = tabName.getTableName();
String nextSynonymSchema = tabName.getSchemaName();
boolean found = false;
CompilerContext cc = getCompilerContext();
// the following loop shouldn't loop forever.
for (; ; ) {
SchemaDescriptor nextSD = getSchemaDescriptor(nextSynonymSchema, false);
if (nextSD == null || nextSD.getUUID() == null)
break;
AliasDescriptor nextAD = dd.getAliasDescriptor(nextSD.getUUID().toString(), nextSynonymTable, AliasInfo.ALIAS_NAME_SPACE_SYNONYM_AS_CHAR);
if (nextAD == null)
break;
/* Query is dependent on the AliasDescriptor */
cc.createDependency(nextAD);
found = true;
SynonymAliasInfo info = ((SynonymAliasInfo) nextAD.getAliasInfo());
nextSynonymTable = info.getSynonymTable();
nextSynonymSchema = info.getSynonymSchema();
}
if (!found)
return null;
TableName tableName = new TableName(nextSynonymSchema, nextSynonymTable, getContextManager());
return tableName;
}
use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class QueryTreeNode method bindUserType.
/**
* Bind a UDT. This involves looking it up in the DataDictionary and filling
* in its class name.
*
* @param originalDTD A datatype: might be an unbound UDT and might not be
*
* @return The bound UDT if originalDTD was an unbound UDT; otherwise returns originalDTD.
*/
public DataTypeDescriptor bindUserType(DataTypeDescriptor originalDTD) throws StandardException {
// if the type is a table type, then we need to bind its user-typed columns
if (originalDTD.getCatalogType().isRowMultiSet()) {
return bindRowMultiSet(originalDTD);
}
// nothing to do if this is not a user defined type
if (!originalDTD.getTypeId().userType()) {
return originalDTD;
}
UserDefinedTypeIdImpl userTypeID = (UserDefinedTypeIdImpl) originalDTD.getTypeId().getBaseTypeId();
// also nothing to do if the type has already been resolved
if (userTypeID.isBound()) {
return originalDTD;
}
// ok, we have an unbound UDT. lookup this type in the data dictionary
DataDictionary dd = getDataDictionary();
SchemaDescriptor typeSchema = getSchemaDescriptor(userTypeID.getSchemaName());
char udtNameSpace = AliasInfo.ALIAS_NAME_SPACE_UDT_AS_CHAR;
String unqualifiedTypeName = userTypeID.getUnqualifiedName();
AliasDescriptor ad = dd.getAliasDescriptor(typeSchema.getUUID().toString(), unqualifiedTypeName, udtNameSpace);
if (ad == null) {
throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, AliasDescriptor.getAliasType(udtNameSpace), unqualifiedTypeName);
}
createTypeDependency(ad);
DataTypeDescriptor result = new DataTypeDescriptor(TypeId.getUserDefinedTypeId(typeSchema.getSchemaName(), unqualifiedTypeName, ad.getJavaClassName()), originalDTD.isNullable());
return result;
}
use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class InsertNode method bindStatement.
/**
* Bind this InsertNode. This means looking up tables and columns and
* getting their types, and figuring out the result types of all
* expressions, as well as doing view resolution, permissions checking,
* etc.
* <p>
* Binding an insert will also massage the tree so that
* the collist and select column order/number are the
* same as the layout of the table in the store.
*
* @exception StandardException Thrown on error
*/
@Override
public void bindStatement() throws StandardException {
// We just need select privilege on the expressions
getCompilerContext().pushCurrentPrivType(Authorizer.SELECT_PRIV);
FromList fromList = new FromList(getOptimizerFactory().doJoinOrderOptimization(), getContextManager());
/* If any underlying ResultSetNode is a SelectNode, then we
* need to do a full bind(), including the expressions
* (since the fromList may include a FromSubquery).
*/
DataDictionary dataDictionary = getDataDictionary();
super.bindResultSetsWithTables(dataDictionary);
/*
** Get the TableDescriptor for the table we are inserting into
*/
verifyTargetTable();
// Check the validity of the targetProperties, if they exist
if (targetProperties != null) {
verifyTargetProperties(dataDictionary);
}
/*
** Get the resultColumnList representing the columns in the base
** table or VTI. We don't bother adding any permission checks here
** because they are assumed by INSERT permission on the table.
*/
IgnoreFilter ignorePermissions = new IgnoreFilter();
getCompilerContext().addPrivilegeFilter(ignorePermissions);
getResultColumnList();
/* If we have a target column list, then it must have the same # of
* entries as the result set's RCL.
*/
if (targetColumnList != null) {
/*
* Normalize synonym qualifers for column references.
*/
if (synonymTableName != null) {
normalizeSynonymColumns(targetColumnList, targetTableName);
}
/* Bind the target column list */
getCompilerContext().pushCurrentPrivType(getPrivType());
if (targetTableDescriptor != null) {
targetColumnList.bindResultColumnsByName(targetTableDescriptor, (DMLStatementNode) this);
} else {
targetColumnList.bindResultColumnsByName(targetVTI.getResultColumns(), targetVTI, this);
}
getCompilerContext().popCurrentPrivType();
}
getCompilerContext().removePrivilegeFilter(ignorePermissions);
/* Verify that all underlying ResultSets reclaimed their FromList */
if (SanityManager.DEBUG) {
SanityManager.ASSERT(fromList.size() == 0, "fromList.size() is expected to be 0, not " + fromList.size() + " on return from RS.bindExpressions()");
}
/* Replace any DEFAULTs with the associated tree, or flag DEFAULTs if
* not allowed (inside top level set operator nodes). Subqueries are
* checked for illegal DEFAULTs elsewhere.
*/
boolean isTableConstructor = (resultSet instanceof UnionNode && ((UnionNode) resultSet).tableConstructor()) || resultSet instanceof RowResultSetNode;
//
// For the MERGE statement, DEFAULT expressions in the SELECT node
// may have been replaced with generated expressions already.
//
ResultColumnList tempRCL = resultSet.getResultColumns();
boolean defaultsWereReplaced = false;
for (int i = 0; i < tempRCL.size(); i++) {
ResultColumn rc = tempRCL.getResultColumn(i + 1);
if (rc.wasDefaultColumn()) {
defaultsWereReplaced = true;
}
}
resultSet.replaceOrForbidDefaults(targetTableDescriptor, targetColumnList, isTableConstructor);
/* Bind the expressions now that the result columns are bound
* NOTE: This will be the 2nd time for those underlying ResultSets
* that have tables (no harm done), but it is necessary for those
* that do not have tables. It's too hard/not work the effort to
* avoid the redundancy.
*/
super.bindExpressions();
//
if (isPrivilegeCollectionRequired()) {
getCompilerContext().pushCurrentPrivType(getPrivType());
getCompilerContext().addRequiredTablePriv(targetTableDescriptor);
getCompilerContext().popCurrentPrivType();
}
// Now stop adding permissions checks.
getCompilerContext().addPrivilegeFilter(ignorePermissions);
/*
** If the result set is a union, it could be a table constructor.
** Bind any nulls in the result columns of the table constructor
** to the types of the table being inserted into.
**
** The types of ? parameters in row constructors and table constructors
** in an INSERT statement come from the result columns.
**
** If there is a target column list, use that instead of the result
** columns for the whole table, since the columns in the result set
** correspond to the target column list.
*/
if (targetColumnList != null) {
if (resultSet.getResultColumns().visibleSize() > targetColumnList.size())
throw StandardException.newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED);
resultSet.bindUntypedNullsToResultColumns(targetColumnList);
resultSet.setTableConstructorTypes(targetColumnList);
} else {
if (resultSet.getResultColumns().visibleSize() > resultColumnList.size())
throw StandardException.newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED);
resultSet.bindUntypedNullsToResultColumns(resultColumnList);
resultSet.setTableConstructorTypes(resultColumnList);
}
/* Bind the columns of the result set to their expressions */
resultSet.bindResultColumns(fromList);
int resCols = resultSet.getResultColumns().visibleSize();
DataDictionary dd = getDataDictionary();
if (targetColumnList != null) {
if (targetColumnList.size() != resCols)
throw StandardException.newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED);
} else {
if (targetTableDescriptor != null && targetTableDescriptor.getNumberOfColumns() != resCols)
throw StandardException.newException(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED);
}
/* See if the ResultSet's RCL needs to be ordered to match the target
* list, or "enhanced" to accommodate defaults. It can only need to
* be ordered if there is a target column list. It needs to be
* enhanced if there are fewer source columns than there are columns
* in the table.
*/
boolean inOrder = true;
int numTableColumns = resultColumnList.size();
/* colMap[] will be the size of the target list, which could be larger
* than the current size of the source list. In that case, the source
* list will be "enhanced" to include defaults.
*/
int[] colMap = new int[numTableColumns];
// set the fields to an unused value
for (int i = 0; i < colMap.length; i++) {
colMap[i] = -1;
}
/* Create the source/target list mapping */
if (targetColumnList != null) {
/*
** There is a target column list, so the result columns might
** need to be ordered. Step through the target column list
** and remember the position in the target table of each column.
** Remember if any of the columns are out of order.
*/
int targetSize = targetColumnList.size();
for (int index = 0; index < targetSize; index++) {
int position = targetColumnList.elementAt(index).getColumnDescriptor().getPosition();
if (index != position - 1) {
inOrder = false;
}
// position is 1-base; colMap indexes and entries are 0-based.
colMap[position - 1] = index;
}
} else {
/*
** There is no target column list, so the result columns in the
** source are presumed to be in the same order as the target
** table.
*/
for (int position = 0; position < resultSet.getResultColumns().visibleSize(); position++) {
colMap[position] = position;
}
}
// Bind the ORDER BY columns
if (orderByList != null) {
orderByList.pullUpOrderByColumns(resultSet);
// The select list may have new columns now, make sure to bind
// those.
super.bindExpressions();
orderByList.bindOrderByColumns(resultSet);
}
bindOffsetFetch(offset, fetchFirst);
resultSet = enhanceAndCheckForAutoincrement(resultSet, inOrder, colMap, defaultsWereReplaced);
resultColumnList.checkStorableExpressions(resultSet.getResultColumns());
/* Insert a NormalizeResultSetNode above the source if the source
* and target column types and lengths do not match.
*/
if (!resultColumnList.columnTypesAndLengthsMatch(resultSet.getResultColumns())) {
resultSet = new NormalizeResultSetNode(resultSet, resultColumnList, null, false, getContextManager());
}
if (targetTableDescriptor != null) {
ResultColumnList sourceRCL = resultSet.getResultColumns();
sourceRCL.copyResultColumnNames(resultColumnList);
/* bind all generation clauses for generated columns */
parseAndBindGenerationClauses(dataDictionary, targetTableDescriptor, sourceRCL, resultColumnList, false, null);
/* Get and bind all constraints on the table */
boolean[] hasDCC = new boolean[] { false /* a priori*/
};
checkConstraints = bindConstraints(dataDictionary, getOptimizerFactory(), targetTableDescriptor, null, sourceRCL, (int[]) null, (FormatableBitSet) null, // we always include triggers in core language
true, hasDCC);
hasDeferrableCheckConstraints = hasDCC[0];
/*
** Deferred if:
** If the target table is also a source table
** Self-referencing foreign key constraint
** trigger
*/
if (resultSet.referencesTarget(targetTableDescriptor.getName(), true) || requiresDeferredProcessing()) {
deferred = true;
/* Disallow bulk insert replace when target table
* is also a source table.
*/
if (bulkInsertReplace && resultSet.referencesTarget(targetTableDescriptor.getName(), true)) {
throw StandardException.newException(SQLState.LANG_INVALID_BULK_INSERT_REPLACE, targetTableDescriptor.getQualifiedName());
}
}
/* Get the list of indexes on the table being inserted into */
getAffectedIndexes(targetTableDescriptor);
TransactionController tc = getLanguageConnectionContext().getTransactionCompile();
autoincRowLocation = dd.computeAutoincRowLocations(tc, targetTableDescriptor);
} else {
deferred = VTIDeferModPolicy.deferIt(DeferModification.INSERT_STATEMENT, targetVTI, null, resultSet);
}
identitySequenceUUIDString = getUUIDofSequenceGenerator();
getCompilerContext().removePrivilegeFilter(ignorePermissions);
getCompilerContext().popCurrentPrivType();
}
use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class ModifyColumnNode method checkExistingConstraints.
/**
* Check if the the column can be modified, and throw error if not.
*
* If the type of a column is being changed (for instance if the length
* of the column is being increased) then make sure that this does not
* violate any key constraints;
* the column being altered is
* 1. part of foreign key constraint
* ==> ERROR. This references a Primary Key constraint and the
* type and lengths of the pkey/fkey must match exactly.
* 2. part of a unique/primary key constraint
* ==> OK if no fkey references this constraint.
* ==> ERROR if any fkey in the system references this constraint.
*
* @param td The Table Descriptor on which the ALTER is being done.
*
* @exception StandardException Thrown on Error.
*/
void checkExistingConstraints(TableDescriptor td) throws StandardException {
if ((kind != K_MODIFY_COLUMN_TYPE) && (kind != K_MODIFY_COLUMN_CONSTRAINT) && (kind != K_MODIFY_COLUMN_CONSTRAINT_NOT_NULL))
return;
DataDictionary dd = getDataDictionary();
ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
int[] intArray = new int[1];
intArray[0] = columnPosition;
for (int index = 0; index < cdl.size(); index++) {
ConstraintDescriptor existingConstraint = cdl.elementAt(index);
if (!(existingConstraint instanceof KeyConstraintDescriptor))
continue;
if (!existingConstraint.columnIntersects(intArray))
continue;
int constraintType = existingConstraint.getConstraintType();
// and fkey columns.
if ((constraintType == DataDictionary.FOREIGNKEY_CONSTRAINT) && (kind == K_MODIFY_COLUMN_TYPE)) {
throw StandardException.newException(SQLState.LANG_MODIFY_COLUMN_FKEY_CONSTRAINT, name, existingConstraint.getConstraintName());
} else {
if (!dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_4, null)) {
// made nullable in soft upgrade mode from a pre-10.4 db.
if (kind == K_MODIFY_COLUMN_CONSTRAINT && (existingConstraint.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT)) {
throw StandardException.newException(SQLState.LANG_MODIFY_COLUMN_EXISTING_CONSTRAINT, name);
}
}
// is being made nullable; can't be done.
if ((kind == K_MODIFY_COLUMN_CONSTRAINT) && ((existingConstraint.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT))) {
String errorState = (getLanguageConnectionContext().getDataDictionary().checkVersion(DataDictionary.DD_VERSION_DERBY_10_4, null)) ? SQLState.LANG_MODIFY_COLUMN_EXISTING_PRIMARY_KEY : SQLState.LANG_MODIFY_COLUMN_EXISTING_CONSTRAINT;
throw StandardException.newException(errorState, name);
}
// unique key or primary key.
ConstraintDescriptorList refcdl = dd.getForeignKeys(existingConstraint.getUUID());
if (refcdl.size() > 0) {
throw StandardException.newException(SQLState.LANG_MODIFY_COLUMN_REFERENCED, name, refcdl.elementAt(0).getConstraintName());
}
// Make the statement dependent on the primary key constraint.
getCompilerContext().createDependency(existingConstraint);
}
}
}
use of org.apache.derby.iapi.sql.dictionary.DataDictionary in project derby by apache.
the class RenameNode method bindStatement.
// We inherit the generate() method from DDLStatementNode.
/**
* Bind this node. This means doing any static error checking that
* can be done before actually renaming the table/column/index.
*
* For a table rename: looking up the from table, verifying it exists
* verifying it's not a system table, verifying it's not view
* and looking up to table, verifying it doesn't exist.
*
* For a column rename: looking up the table, verifying it exists,
* verifying it's not a system table, verifying it's not view, verifying
* the from column exists, verifying the to column doesn't exist.
*
* For a index rename: looking up the table, verifying it exists,
* verifying it's not a system table, verifying it's not view, verifying
* the from index exists, verifying the to index doesn't exist.
*
* @exception StandardException Thrown on error
*/
@Override
public void bindStatement() throws StandardException {
CompilerContext cc = getCompilerContext();
DataDictionary dd = getDataDictionary();
ConglomerateDescriptor cd;
SchemaDescriptor sd;
/* in case of rename index, the only thing we get from parser is
* current and new index names with no information about the
* table it belongs to. This is because index names are unique
* within a schema and hence then is no need to qualify an index
* name with a table name which we have to do for rename column.
* But from the index name, using the data dictionary, you can
* find the table it belongs to. Since most of the checking
* in bind is done using table descriptor, in the following if
* statement, we are trying to get the table information from the
* index name so it is available for the rest of he bind code.
*/
TableName baseTable;
if (renamingWhat == StatementType.RENAME_INDEX) {
sd = getSchemaDescriptor((String) null);
ConglomerateDescriptor indexDescriptor = dd.getConglomerateDescriptor(oldObjectName, sd, false);
if (indexDescriptor == null)
throw StandardException.newException(SQLState.LANG_INDEX_NOT_FOUND, oldObjectName);
/* Get the table descriptor */
td = dd.getTableDescriptor(indexDescriptor.getTableID());
initAndCheck(makeTableName(td.getSchemaName(), td.getName()));
} else
sd = getSchemaDescriptor();
td = getTableDescriptor();
// throw an exception if user is attempting a rename on temporary table
if (td.getTableType() == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE) {
throw StandardException.newException(SQLState.LANG_NOT_ALLOWED_FOR_DECLARED_GLOBAL_TEMP_TABLE);
}
switch(this.renamingWhat) {
case StatementType.RENAME_TABLE:
/* Verify that new table name does not exist in the database */
TableDescriptor tabDesc = getTableDescriptor(newObjectName, sd);
if (tabDesc != null)
throw descriptorExistsException(tabDesc, sd);
renameTableBind(dd);
break;
case StatementType.RENAME_COLUMN:
renameColumnBind(dd);
break;
case StatementType.RENAME_INDEX:
ConglomerateDescriptor conglomDesc = dd.getConglomerateDescriptor(newObjectName, sd, false);
if (conglomDesc != null)
throw descriptorExistsException(conglomDesc, sd);
break;
default:
if (SanityManager.DEBUG)
SanityManager.THROWASSERT("Unexpected rename action in RenameNode");
break;
}
conglomerateNumber = td.getHeapConglomerateId();
/* Get the base conglomerate descriptor */
cd = td.getConglomerateDescriptor(conglomerateNumber);
/* Statement is dependent on the TableDescriptor and ConglomerateDescriptor */
cc.createDependency(td);
cc.createDependency(cd);
}
Aggregations