use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList in project derby by apache.
the class DMLModStatementNode method generateCheckTree.
/**
* Get the ANDing of all appropriate check constraints as 1 giant query tree.
*
* Makes the calling object (usually a Statement) dependent on all the constraints.
*
* @param cdl The constraint descriptor list
* @param td The TableDescriptor
*
* @return The ANDing of all appropriate check constraints as a query tree.
*
* @exception StandardException Thrown on failure
*/
private ValueNode generateCheckTree(ConstraintDescriptorList cdl, TableDescriptor td, boolean[] hasDeferrable) throws StandardException {
ConstraintDescriptorList ccCDL = cdl.getSubList(DataDictionary.CHECK_CONSTRAINT);
int ccCDLSize = ccCDL.size();
ValueNode checkTree = null;
for (ConstraintDescriptor cd : ccCDL) {
if (cd.deferrable()) {
hasDeferrable[0] = true;
break;
}
}
// Get the text of all the check constraints
for (int index = 0; index < ccCDLSize; index++) {
ConstraintDescriptor cd = ccCDL.elementAt(index);
String constraintText = cd.getConstraintText();
// Get the query tree for this constraint
ValueNode oneConstraint = parseCheckConstraint(constraintText, td);
// Put a TestConstraintNode above the constraint tree
TestConstraintNode tcn = new TestConstraintNode(oneConstraint, SQLState.LANG_CHECK_CONSTRAINT_VIOLATED, td.getQualifiedName(), cd, getContextManager());
// Link consecutive TestConstraintNodes with AND nodes
if (checkTree == null) {
checkTree = tcn;
} else {
if (hasDeferrable[0]) {
checkTree = new AndNoShortCircuitNode(tcn, checkTree, getContextManager());
} else {
checkTree = new AndNode(tcn, checkTree, getContextManager());
}
}
}
return checkTree;
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList in project derby by apache.
the class DMLModStatementNode method hasCheckConstraints.
/**
* Determine whether or not there are check constraints on the
* specified table.
*
* @param dd The DataDictionary to use
* @param td The TableDescriptor for the table
*
* @return Whether or not there are check constraints on the specified table.
*
* @exception StandardException Thrown on failure
*/
protected boolean hasCheckConstraints(DataDictionary dd, TableDescriptor td) throws StandardException {
ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
if (cdl == null)
return false;
ConstraintDescriptorList ccCDL = cdl.getSubList(DataDictionary.CHECK_CONSTRAINT);
return (ccCDL.size() > 0);
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList in project derby by apache.
the class DMLModStatementNode method getAllRelevantConstraints.
/**
* Get all the constraints relevant to this DML operation
*
* @param dd The DataDictionary
* @param td The TableDescriptor
* @param changedColumnIds If null, all columns being changed, otherwise array
* of 1-based column ids for columns being changed
*
* @return the constraint descriptor list
*
* @exception StandardException Thrown on failure
*/
protected ConstraintDescriptorList getAllRelevantConstraints(DataDictionary dd, TableDescriptor td, int[] changedColumnIds) throws StandardException {
if (relevantCdl != null) {
return relevantCdl;
}
boolean[] needsDeferredProcessing = new boolean[1];
relevantCdl = new ConstraintDescriptorList();
needsDeferredProcessing[0] = requiresDeferredProcessing;
td.getAllRelevantConstraints(statementType, changedColumnIds, needsDeferredProcessing, relevantCdl);
adjustDeferredFlag(needsDeferredProcessing[0]);
return relevantCdl;
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList in project derby by apache.
the class TableElementList method validate.
/**
* Validate this TableElementList. This includes checking for
* duplicate columns names, and checking that user types really exist.
*
* @param ddlStmt DDLStatementNode which contains this list
* @param dd DataDictionary to use
* @param td TableDescriptor for table, if existing table.
*
* @exception StandardException Thrown on error
*/
void validate(DDLStatementNode ddlStmt, DataDictionary dd, TableDescriptor td) throws StandardException {
this.td = td;
int numAutoCols = 0;
int size = size();
HashSet<String> columnNames = new HashSet<String>(size + 2, 0.999f);
HashSet<String> constraintNames = new HashSet<String>(size + 2, 0.999f);
// all the primary key/unique key constraints for this table
ArrayList<Object> constraints = new ArrayList<Object>();
// special case for alter table (td is not null in case of alter table)
if (td != null) {
// In case of alter table, get the already existing primary key and unique
// key constraints for this table. And then we will compare them with new
// primary key/unique key constraint column lists.
ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
ConstraintDescriptor cd;
if (// table does have some pre-existing constraints defined on it
cdl != null) {
for (int i = 0; i < cdl.size(); i++) {
cd = cdl.elementAt(i);
// if the constraint type is not primary key or unique key, ignore it.
if (cd.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT || cd.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT) {
constraints.add(cd);
}
}
}
}
int tableType = TableDescriptor.BASE_TABLE_TYPE;
if (ddlStmt instanceof CreateTableNode)
tableType = ((CreateTableNode) ddlStmt).tableType;
for (TableElementNode tableElement : this) {
if (tableElement instanceof ColumnDefinitionNode) {
ColumnDefinitionNode cdn = (ColumnDefinitionNode) tableElement;
if (tableType == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE && (cdn.getType().getTypeId().isLongConcatableTypeId() || cdn.getType().getTypeId().isUserDefinedTypeId())) {
throw StandardException.newException(SQLState.LANG_LONG_DATA_TYPE_NOT_ALLOWED, cdn.getColumnName());
}
checkForDuplicateColumns(ddlStmt, columnNames, cdn.getColumnName());
cdn.checkUserType(td);
cdn.bindAndValidateDefault(dd, td);
cdn.validateAutoincrement(dd, td, tableType);
if (tableElement instanceof ModifyColumnNode) {
ModifyColumnNode mcdn = (ModifyColumnNode) cdn;
mcdn.checkExistingConstraints(td);
mcdn.useExistingCollation(td);
} else if (cdn.isAutoincrementColumn()) {
numAutoCols++;
}
} else if (tableElement.getElementType() == TableElementNode.AT_DROP_COLUMN) {
String colName = tableElement.getName();
if (td.getColumnDescriptor(colName) == null) {
throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, colName, td.getQualifiedName());
}
break;
}
/* The rest of this method deals with validating constraints */
if (!(tableElement.hasConstraint())) {
continue;
}
ConstraintDefinitionNode cdn = (ConstraintDefinitionNode) tableElement;
cdn.bind(ddlStmt, dd);
// If constraint is primary key or unique key, add it to the list.
if (cdn.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT || cdn.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT) {
/* In case of create table, the list can have only ConstraintDefinitionNode
* elements. In case of alter table, it can have both ConstraintDefinitionNode
* (for new constraints) and ConstraintDescriptor(for pre-existing constraints).
*/
Object destConstraint;
String destName = null;
String[] destColumnNames = null;
for (int i = 0; i < constraints.size(); i++) {
destConstraint = constraints.get(i);
if (destConstraint instanceof ConstraintDefinitionNode) {
ConstraintDefinitionNode destCDN = (ConstraintDefinitionNode) destConstraint;
destName = destCDN.getConstraintMoniker();
destColumnNames = destCDN.getColumnList().getColumnNames();
} else if (destConstraint instanceof ConstraintDescriptor) {
// will come here only for pre-existing constraints in case of alter table
ConstraintDescriptor destCD = (ConstraintDescriptor) destConstraint;
destName = destCD.getConstraintName();
destColumnNames = destCD.getColumnDescriptors().getColumnNames();
}
// check if there are multiple constraints with same set of columns
if (columnsMatch(cdn.getColumnList().getColumnNames(), destColumnNames))
throw StandardException.newException(SQLState.LANG_MULTIPLE_CONSTRAINTS_WITH_SAME_COLUMNS, cdn.getConstraintMoniker(), destName);
}
constraints.add(cdn);
}
/* Make sure that there are no duplicate constraint names in the list */
checkForDuplicateConstraintNames(ddlStmt, constraintNames, cdn.getConstraintMoniker());
/* Make sure that the constraint we are trying to drop exists */
if (cdn.getConstraintType() == DataDictionary.DROP_CONSTRAINT || cdn.getConstraintType() == DataDictionary.MODIFY_CONSTRAINT) {
/*
** If no schema descriptor, then must be an invalid
** schema name.
*/
String dropConstraintName = cdn.getConstraintMoniker();
if (dropConstraintName != null) {
String dropSchemaName = cdn.getDropSchemaName();
SchemaDescriptor sd = dropSchemaName == null ? td.getSchemaDescriptor() : getSchemaDescriptor(dropSchemaName);
ConstraintDescriptor cd = dd.getConstraintDescriptorByName(td, sd, dropConstraintName, false);
if (cd == null) {
throw StandardException.newException(SQLState.LANG_DROP_OR_ALTER_NON_EXISTING_CONSTRAINT, (sd.getSchemaName() + "." + dropConstraintName), td.getQualifiedName());
}
/* Statement is dependendent on the ConstraintDescriptor */
getCompilerContext().createDependency(cd);
}
}
// validation of primary key nullability moved to validatePrimaryKeyNullability().
if (cdn.hasPrimaryKeyConstraint()) {
// for PRIMARY KEY, check that columns are unique
verifyUniqueColumnList(ddlStmt, cdn);
} else if (cdn.hasUniqueKeyConstraint()) {
// for UNIQUE, check that columns are unique
verifyUniqueColumnList(ddlStmt, cdn);
// disallow until database hard upgraded at least to 10.4.
if (!dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_4, null)) {
checkForNullColumns(cdn, td);
}
} else if (cdn.hasForeignKeyConstraint()) {
// for FOREIGN KEY, check that columns are unique
verifyUniqueColumnList(ddlStmt, cdn);
}
}
// with ALTER TABLE ADD COLUMN.
if (numAutoCols > 1 || (numAutoCols > 0 && td != null && td.tableHasAutoincrement())) {
throw StandardException.newException(SQLState.LANG_MULTIPLE_AUTOINCREMENT_COLUMNS);
}
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList in project derby by apache.
the class AlterTableConstantAction method modifyColumnConstraint.
/**
* Workhorse for modifying column level constraints.
* Right now it is restricted to modifying a null constraint to a not null
* constraint.
*/
private void modifyColumnConstraint(String colName, boolean nullability) throws StandardException {
ColumnDescriptor columnDescriptor = td.getColumnDescriptor(colName);
// Get the type and change the nullability
DataTypeDescriptor dataType = columnDescriptor.getType().getNullabilityType(nullability);
// check if there are any unique constraints to update
ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
int columnPostion = columnDescriptor.getPosition();
for (int i = 0; i < cdl.size(); i++) {
ConstraintDescriptor cd = cdl.elementAt(i);
if (cd.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT) {
ColumnDescriptorList columns = cd.getColumnDescriptors();
for (int count = 0; count < columns.size(); count++) {
if (columns.elementAt(count).getPosition() != columnPostion)
break;
// get backing index
ConglomerateDescriptor desc = td.getConglomerateDescriptor(cd.getConglomerateId());
// not null ie is backed by unique index
if (!(desc.getIndexDescriptor().isUnique() || desc.getIndexDescriptor().hasDeferrableChecking())) {
break;
}
// replace backing index with a unique when not null index.
recreateUniqueConstraintBackingIndexAsUniqueWhenNotNull(desc, td, activation, lcc);
}
}
}
ColumnDescriptor newColumnDescriptor = new ColumnDescriptor(colName, columnDescriptor.getPosition(), dataType, columnDescriptor.getDefaultValue(), columnDescriptor.getDefaultInfo(), td, columnDescriptor.getDefaultUUID(), columnDescriptor.getAutoincStart(), columnDescriptor.getAutoincInc(), columnDescriptor.getAutoincCycle());
// Update the ColumnDescriptor with new default info
dd.dropColumnDescriptor(td.getUUID(), colName, tc);
dd.addDescriptor(newColumnDescriptor, td, DataDictionary.SYSCOLUMNS_CATALOG_NUM, false, tc);
}
Aggregations