use of org.apache.derby.impl.sql.execute.ConstraintInfo in project derby by apache.
the class TableElementList method genConstraintActions.
/**
* Fill in the ConstraintConstantAction[] for this create/alter table.
*
* @param forCreateTable ConstraintConstantAction is for a create table.
* @param conActions The ConstraintConstantAction[] to be filled in.
* @param tableName The name of the Table being created.
* @param tableSd The schema for that table.
* @param dd The DataDictionary
*
* @exception StandardException Thrown on failure
*/
void genConstraintActions(boolean forCreateTable, ConstraintConstantAction[] conActions, String tableName, SchemaDescriptor tableSd, DataDictionary dd) throws StandardException {
int conActionIndex = 0;
for (TableElementNode ten : this) {
String[] columnNames = null;
IndexConstantAction indexAction = null;
if (!ten.hasConstraint() || ten instanceof ColumnDefinitionNode) {
continue;
}
ConstraintDefinitionNode constraintDN = (ConstraintDefinitionNode) ten;
if (constraintDN.getColumnList() != null) {
columnNames = new String[constraintDN.getColumnList().size()];
constraintDN.getColumnList().exportNames(columnNames);
}
int constraintType = constraintDN.getConstraintType();
boolean[] cChars = constraintDN.getCharacteristics();
String constraintText = constraintDN.getConstraintText();
/*
** If the constraint is not named (e.g.
** create table x (x int primary key)), then
** the constraintSd is the same as the table.
*/
String constraintName = constraintDN.getConstraintMoniker();
/* At execution time, we will generate a unique name for the backing
* index (for CREATE CONSTRAINT) and we will look up the conglomerate
* name (for DROP CONSTRAINT).
*/
if (constraintDN.requiresBackingIndex()) {
if (constraintDN.constraintType == DataDictionary.UNIQUE_CONSTRAINT && (dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_4, null))) {
boolean contains_nullable_columns = areColumnsNullable(constraintDN, td);
// if all the columns are non nullable, continue to use
// a unique backing index.
boolean unique = !contains_nullable_columns;
// Only use a "unique with duplicate nulls" backing index
// for constraints with nullable columns.
boolean uniqueWithDuplicateNulls = contains_nullable_columns;
indexAction = genIndexAction(forCreateTable, unique, uniqueWithDuplicateNulls, // deferrable?
cChars[0], // initiallyDeferred?
cChars[1], null, constraintDN, columnNames, true, tableSd, tableName, constraintType, dd);
} else {
// PRIMARY KEY, FOREIGN KEY
// For foreign key constraint we do no mark the
// index as deferrable; since checking isn't done on
// duplicate keys there.
indexAction = genIndexAction(forCreateTable, constraintDN.requiresUniqueIndex(), false, cChars[0], cChars[1], null, constraintDN, columnNames, true, tableSd, tableName, constraintType, dd);
}
}
if (constraintType == DataDictionary.DROP_CONSTRAINT) {
if (SanityManager.DEBUG) {
// Can't drop constraints on a create table.
SanityManager.ASSERT(!forCreateTable);
}
conActions[conActionIndex] = getGenericConstantActionFactory().getDropConstraintConstantAction(constraintName, // / FiX
constraintDN.getDropSchemaName(), tableName, td.getUUID(), tableSd.getSchemaName(), indexAction, constraintDN.getDropBehavior(), constraintDN.getVerifyType());
} else if (constraintType == DataDictionary.MODIFY_CONSTRAINT) {
conActions[conActionIndex] = getGenericConstantActionFactory().getAlterConstraintConstantAction(constraintName, constraintDN.getDropSchemaName(), cChars, tableName, td.getUUID(), tableSd.getSchemaName(), indexAction);
} else {
ProviderList apl = constraintDN.getAuxiliaryProviderList();
ConstraintInfo refInfo = null;
ProviderInfo[] providerInfos;
if (constraintDN instanceof FKConstraintDefinitionNode) {
refInfo = ((FKConstraintDefinitionNode) constraintDN).getReferencedConstraintInfo();
}
/* Create the ProviderInfos, if the constraint is dependent on any Providers */
if (apl != null && apl.size() > 0) {
/* Get all the dependencies for the current statement and transfer
* them to this view.
*/
DependencyManager dm = dd.getDependencyManager();
providerInfos = dm.getPersistentProviderInfos(apl);
} else {
providerInfos = new ProviderInfo[0];
// System.out.println("TABLE ELEMENT LIST EMPTY");
}
conActions[conActionIndex++] = getGenericConstantActionFactory().getCreateConstraintConstantAction(constraintName, constraintType, cChars, forCreateTable, tableName, ((td != null) ? td.getUUID() : (UUID) null), tableSd.getSchemaName(), columnNames, indexAction, constraintText, refInfo, providerInfos);
}
}
}
use of org.apache.derby.impl.sql.execute.ConstraintInfo in project derby by apache.
the class TableElementList method validateForeignKeysOnGenerationClauses.
/**
* Prevent foreign keys on generated columns from violating the SQL spec,
* part 2, section 11.8 (<column definition>), syntax rule 12: the
* referential action may not specify SET NULL or SET DEFAULT and the update
* rule may not specify ON UPDATE CASCADE.
*
* @param fromList The FromList in question.
* @param generatedColumns Bitmap of generated columns in the table.
*
* @exception StandardException Thrown on error
*/
void validateForeignKeysOnGenerationClauses(FromList fromList, FormatableBitSet generatedColumns) throws StandardException {
// nothing to do if there are no generated columns
if (generatedColumns.getNumBitsSet() <= 0) {
return;
}
FromBaseTable table = (FromBaseTable) fromList.elementAt(0);
ResultColumnList tableColumns = table.getResultColumns();
// rulse we're enforcing
for (TableElementNode element : this) {
if (!(element instanceof FKConstraintDefinitionNode)) {
continue;
}
FKConstraintDefinitionNode fk = (FKConstraintDefinitionNode) element;
ConstraintInfo ci = fk.getReferencedConstraintInfo();
int deleteRule = ci.getReferentialActionDeleteRule();
int updateRule = ci.getReferentialActionUpdateRule();
//
if ((updateRule != StatementType.RA_RESTRICT) && (updateRule != StatementType.RA_NOACTION)) {
throw StandardException.newException(SQLState.BTREE_UNIMPLEMENTED_FEATURE);
}
if ((deleteRule != StatementType.RA_SETNULL) && (deleteRule != StatementType.RA_SETDEFAULT)) {
continue;
}
//
for (ResultColumn keyCol : fk.getColumnList()) {
String keyColName = keyCol.getName();
int position = tableColumns.getPosition(keyColName, 1);
if (generatedColumns.isSet(position)) {
throw StandardException.newException(SQLState.LANG_BAD_FK_ON_GENERATED_COLUMN, keyColName);
}
}
}
// end of loop through table elements
}
Aggregations