use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor 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.ConstraintDescriptor in project derby by apache.
the class RenameNode method renameColumnBind.
// do any checking needs to be done at bind time for rename column
private void renameColumnBind(DataDictionary dd) throws StandardException {
ColumnDescriptor columnDescriptor = td.getColumnDescriptor(oldObjectName);
/* Verify that old column name does exist in the table */
if (columnDescriptor == null)
throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, oldObjectName, getFullName());
/* Verify that new column name does not exist in the table */
ColumnDescriptor cd = td.getColumnDescriptor(newObjectName);
if (cd != null)
throw descriptorExistsException(cd, td);
//
// You cannot rename a column which is referenced by the generation
// clause of a generated column.
//
ColumnDescriptorList generatedColumns = td.getGeneratedColumns();
int generatedColumnCount = generatedColumns.size();
for (int i = 0; i < generatedColumnCount; i++) {
ColumnDescriptor gc = generatedColumns.elementAt(i);
String[] referencedColumns = gc.getDefaultInfo().getReferencedColumnNames();
int refColCount = referencedColumns.length;
for (int j = 0; j < refColCount; j++) {
String refName = referencedColumns[j];
if (oldObjectName.equals(refName)) {
throw StandardException.newException(SQLState.LANG_GEN_COL_BAD_RENAME, oldObjectName, gc.getColumnName());
}
}
}
/* Verify that there are no check constraints using the column being renamed */
ConstraintDescriptorList constraintDescriptorList = dd.getConstraintDescriptors(td);
int size = constraintDescriptorList == null ? 0 : constraintDescriptorList.size();
ConstraintDescriptor constraintDescriptor;
ColumnDescriptorList checkConstraintCDL;
int checkConstraintCDLSize;
// go through all the constraints defined on the table
for (int index = 0; index < size; index++) {
constraintDescriptor = constraintDescriptorList.elementAt(index);
// renamed is not used in it's sql
if (constraintDescriptor.getConstraintType() == DataDictionary.CHECK_CONSTRAINT) {
checkConstraintCDL = constraintDescriptor.getColumnDescriptors();
checkConstraintCDLSize = checkConstraintCDL.size();
for (int index2 = 0; index2 < checkConstraintCDLSize; index2++) if (checkConstraintCDL.elementAt(index2) == columnDescriptor)
throw StandardException.newException(SQLState.LANG_RENAME_COLUMN_WILL_BREAK_CHECK_CONSTRAINT, oldObjectName, constraintDescriptor.getConstraintName());
}
}
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor in project derby by apache.
the class FromBaseTable method pushIndexName.
/* helper method used by generateMaxSpecialResultSet and
* generateDistinctScan to return the name of the index if the
* conglomerate is an index.
* @param cd Conglomerate for which we need to push the index name
* @param mb Associated MethodBuilder
* @throws StandardException
*/
private void pushIndexName(ConglomerateDescriptor cd, MethodBuilder mb) throws StandardException {
if (cd.isConstraint()) {
DataDictionary dd = getDataDictionary();
ConstraintDescriptor constraintDesc = dd.getConstraintDescriptor(tableDescriptor, cd.getUUID());
mb.push(constraintDesc.getConstraintName());
} else if (cd.isIndex()) {
mb.push(cd.getConglomerateName());
} else {
// If the conglomerate is the base table itself, make sure we push
// null. Before the fix for DERBY-578, we would push the base table
// name and this was just plain wrong and would cause statistics
// information to be incorrect.
mb.pushNull("java.lang.String");
}
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor in project derby by apache.
the class FromBaseTable method verifyProperties.
/**
* @see org.apache.derby.iapi.sql.compile.Optimizable#verifyProperties
* @exception StandardException Thrown on error
*/
@Override
public void verifyProperties(DataDictionary dDictionary) throws StandardException {
if (tableProperties == null) {
return;
}
/* Check here for:
* invalid properties key
* index and constraint properties
* non-existent index
* non-existent constraint
* invalid joinStrategy
* invalid value for hashInitialCapacity
* invalid value for hashLoadFactor
* invalid value for hashMaxCapacity
*/
boolean indexSpecified = false;
boolean constraintSpecified = false;
ConstraintDescriptor consDesc = null;
Enumeration<?> e = tableProperties.keys();
StringUtil.SQLEqualsIgnoreCase(tableDescriptor.getSchemaName(), "SYS");
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
String value = (String) tableProperties.get(key);
if (key.equals("index")) {
// User only allowed to specify 1 of index and constraint, not both
if (constraintSpecified) {
throw StandardException.newException(SQLState.LANG_BOTH_FORCE_INDEX_AND_CONSTRAINT_SPECIFIED, getBaseTableName());
}
indexSpecified = true;
/* Validate index name - NULL means table scan */
if (!StringUtil.SQLToUpperCase(value).equals("NULL")) {
ConglomerateDescriptor cd = null;
ConglomerateDescriptor[] cds = tableDescriptor.getConglomerateDescriptors();
for (int index = 0; index < cds.length; index++) {
cd = cds[index];
String conglomerateName = cd.getConglomerateName();
if (conglomerateName != null) {
if (conglomerateName.equals(value)) {
break;
}
}
// Not a match, clear cd
cd = null;
}
// Throw exception if user specified index not found
if (cd == null) {
throw StandardException.newException(SQLState.LANG_INVALID_FORCED_INDEX1, value, getBaseTableName());
}
/* Query is dependent on the ConglomerateDescriptor */
getCompilerContext().createDependency(cd);
}
} else if (key.equals("constraint")) {
// User only allowed to specify 1 of index and constraint, not both
if (indexSpecified) {
throw StandardException.newException(SQLState.LANG_BOTH_FORCE_INDEX_AND_CONSTRAINT_SPECIFIED, getBaseTableName());
}
constraintSpecified = true;
if (!StringUtil.SQLToUpperCase(value).equals("NULL")) {
consDesc = dDictionary.getConstraintDescriptorByName(tableDescriptor, (SchemaDescriptor) null, value, false);
/* Throw exception if user specified constraint not found
* or if it does not have a backing index.
*/
if ((consDesc == null) || !consDesc.hasBackingIndex()) {
throw StandardException.newException(SQLState.LANG_INVALID_FORCED_INDEX2, value, getBaseTableName());
}
/* Query is dependent on the ConstraintDescriptor */
getCompilerContext().createDependency(consDesc);
}
} else if (key.equals("joinStrategy")) {
userSpecifiedJoinStrategy = StringUtil.SQLToUpperCase(value);
} else if (key.equals("hashInitialCapacity")) {
initialCapacity = getIntProperty(value, key);
// verify that the specified value is valid
if (initialCapacity <= 0) {
throw StandardException.newException(SQLState.LANG_INVALID_HASH_INITIAL_CAPACITY, String.valueOf(initialCapacity));
}
} else if (key.equals("hashLoadFactor")) {
try {
loadFactor = Float.parseFloat(value);
} catch (NumberFormatException nfe) {
throw StandardException.newException(SQLState.LANG_INVALID_NUMBER_FORMAT_FOR_OVERRIDE, value, key);
}
// verify that the specified value is valid
if (loadFactor <= 0.0 || loadFactor > 1.0) {
throw StandardException.newException(SQLState.LANG_INVALID_HASH_LOAD_FACTOR, value);
}
} else if (key.equals("hashMaxCapacity")) {
maxCapacity = getIntProperty(value, key);
// verify that the specified value is valid
if (maxCapacity <= 0) {
throw StandardException.newException(SQLState.LANG_INVALID_HASH_MAX_CAPACITY, String.valueOf(maxCapacity));
}
} else if (key.equals("bulkFetch")) {
bulkFetch = getIntProperty(value, key);
// verify that the specified value is valid
if (bulkFetch <= 0) {
throw StandardException.newException(SQLState.LANG_INVALID_BULK_FETCH_VALUE, String.valueOf(bulkFetch));
}
// no bulk fetch on updatable scans
if (forUpdate()) {
throw StandardException.newException(SQLState.LANG_INVALID_BULK_FETCH_UPDATEABLE);
}
} else if (key.equals("validateCheckConstraint")) {
// the property "validateCheckConstraint" is read earlier
// cf. isValidatingCheckConstraint
} else {
// No other "legal" values at this time
throw StandardException.newException(SQLState.LANG_INVALID_FROM_TABLE_PROPERTY, key, "index, constraint, joinStrategy");
}
}
/* If user specified a non-null constraint name(DERBY-1707), then
* replace it in the properties list with the underlying index name to
* simplify the code in the optimizer.
* NOTE: The code to get from the constraint name, for a constraint
* with a backing index, to the index name is convoluted. Given
* the constraint name, we can get the conglomerate id from the
* ConstraintDescriptor. We then use the conglomerate id to get
* the ConglomerateDescriptor from the DataDictionary and, finally,
* we get the index name (conglomerate name) from the ConglomerateDescriptor.
*/
if (constraintSpecified && consDesc != null) {
ConglomerateDescriptor cd = dDictionary.getConglomerateDescriptor(consDesc.getConglomerateId());
String indexName = cd.getConglomerateName();
tableProperties.remove("constraint");
tableProperties.put("index", indexName);
}
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor 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;
}
Aggregations