*
* @exception StandardException Thrown on error
*/
public void bindStatement() throws StandardException
{
DataDictionary dd = getDataDictionary();
int numCheckConstraints = 0;
int numReferenceConstraints = 0;
int numGenerationClauses = 0;
int numBackingIndexes = 0;
/*
** Get the table descriptor. Checks the schema
** and the table.
*/
if(compressTable && (purge || defragment || truncateEndOfTable)) {
//We are dealing with inplace compress here and inplace compress is
//allowed on system schemas. In order to support inplace compress
//on user as well as system tables, we need to use special
//getTableDescriptor(boolean) call to get TableDescriptor. This
//getTableDescriptor(boolean) allows getting TableDescriptor for
//system tables without throwing an exception.
baseTable = getTableDescriptor(false);
} else
baseTable = getTableDescriptor();
//throw an exception if user is attempting to alter a temporary table
if (baseTable.getTableType() == TableDescriptor.GLOBAL_TEMPORARY_TABLE_TYPE)
{
throw StandardException.newException(SQLState.LANG_NOT_ALLOWED_FOR_DECLARED_GLOBAL_TEMP_TABLE);
}
/* Statement is dependent on the TableDescriptor */
getCompilerContext().createDependency(baseTable);
//If we are dealing with add column character type, then set that
//column's collation type to be the collation type of the schema.
//The collation derivation of such a column would be "implicit".
if (changeType == ADD_TYPE) {//the action is of type add.
if (tableElementList != null) {//check if is is add column
for (int i=0; i<tableElementList.size();i++) {
if (tableElementList.elementAt(i) instanceof ColumnDefinitionNode) {
ColumnDefinitionNode cdn = (ColumnDefinitionNode) tableElementList.elementAt(i);
//check if we are dealing with add character column
//
// For generated columns which omit an explicit
// datatype, we have to defer this work until we bind
// the generation clause
//
if ( cdn.hasGenerationClause() && ( cdn.getType() == null ) ) { continue; }
if ( cdn.getType() == null )
{
throw StandardException.newException
( SQLState.LANG_NEEDS_DATATYPE, cdn.getColumnName() );
}
if (cdn.getType().getTypeId().isStringTypeId()) {
//we found what we are looking for. Set the
//collation type of this column to be the same as
//schema descriptor's collation. Set the collation
//derivation as implicit
cdn.setCollationType(schemaDescriptor.getCollationType());
}
}
}
}
}
if (tableElementList != null)
{
tableElementList.validate(this, dd, baseTable);
/* Only 1012 columns allowed per table */
if ((tableElementList.countNumberOfColumns() + baseTable.getNumberOfColumns()) > Limits.DB2_MAX_COLUMNS_IN_TABLE)
{
throw StandardException.newException(SQLState.LANG_TOO_MANY_COLUMNS_IN_TABLE_OR_VIEW,
String.valueOf(tableElementList.countNumberOfColumns() + baseTable.getNumberOfColumns()),
getRelativeName(),
String.valueOf(Limits.DB2_MAX_COLUMNS_IN_TABLE));
}
/* Number of backing indexes in the alter table statment */
numBackingIndexes = tableElementList.countConstraints(DataDictionary.PRIMARYKEY_CONSTRAINT) +
tableElementList.countConstraints(DataDictionary.FOREIGNKEY_CONSTRAINT) +
tableElementList.countConstraints(DataDictionary.UNIQUE_CONSTRAINT);
/* Check the validity of all check constraints */
numCheckConstraints = tableElementList.countConstraints(
DataDictionary.CHECK_CONSTRAINT);
numReferenceConstraints = tableElementList.countConstraints(
DataDictionary.FOREIGNKEY_CONSTRAINT);
numGenerationClauses = tableElementList.countGenerationClauses();
}
//If the sum of backing indexes for constraints in alter table statement and total number of indexes on the table
//so far is more than 32767, then we need to throw an exception
if ((numBackingIndexes + baseTable.getTotalNumberOfIndexes()) > Limits.DB2_MAX_INDEXES_ON_TABLE)
{
throw StandardException.newException(SQLState.LANG_TOO_MANY_INDEXES_ON_TABLE,
String.valueOf(numBackingIndexes + baseTable.getTotalNumberOfIndexes()),
getRelativeName(),
String.valueOf(Limits.DB2_MAX_INDEXES_ON_TABLE));
}
if ( (numCheckConstraints > 0) || (numGenerationClauses > 0) || (numReferenceConstraints > 0))
{
/* In order to check the validity of the check constraints and
* generation clauses
* we must goober up a FromList containing a single table,
* the table being alter, with an RCL containing the existing and
* new columns and their types. This will allow us to
* bind the constraint definition trees against that
* FromList. When doing this, we verify that there are
* no nodes which can return non-deterministic results.
*/
FromList fromList = makeFromList( dd, tableElementList, false );
FormatableBitSet generatedColumns = baseTable.makeColumnMap( baseTable.getGeneratedColumns() );
/* Now that we've finally goobered stuff up, bind and validate
* the check constraints and generation clauses.
*/
if (numGenerationClauses > 0)
{ tableElementList.bindAndValidateGenerationClauses( schemaDescriptor, fromList, generatedColumns, baseTable ); }
if (numCheckConstraints > 0) { tableElementList.bindAndValidateCheckConstraints(fromList); }
if ( numReferenceConstraints > 0) { tableElementList.validateForeignKeysOnGenerationClauses( fromList, generatedColumns ); }
}
// must be done after resolving the datatypes of the generation clauses
if (tableElementList != null) { tableElementList.validatePrimaryKeyNullability(); }
//Check if we are in alter table to update the statistics. If yes, then
//check if we are here to update the statistics of a specific index. If
//yes, then verify that the indexname provided is a valid one.
if (updateStatistics && !updateStatisticsAll)
{
ConglomerateDescriptor cd = null;
if (schemaDescriptor.getUUID() != null)
cd = dd.getConglomerateDescriptor(indexNameForUpdateStatistics, schemaDescriptor, false);
if (cd == null)
{
throw StandardException.newException(
SQLState.LANG_INDEX_NOT_FOUND,