📄 altertableconstantaction.java
字号:
} else if (columnInfo[ix].action == ColumnInfo.MODIFY_COLUMN_CONSTRAINT_NOT_NULL) { if (! tableScanned) { tableScanned = true; numRows = getSemiRowCount(tc); } // check that the data in the column is not null String colNames[] = new String[1]; colNames[0] = columnInfo[ix].name; boolean nullCols[] = new boolean[1]; /* note validateNotNullConstraint returns true if the * column is nullable */ if (validateNotNullConstraint(colNames, nullCols, numRows, lcc, SQLState.LANG_NULL_DATA_IN_NON_NULL_COLUMN)) { /* nullable column - modify it to be not null * This is O.K. at this point since we would have * thrown an exception if any data was null */ modifyColumnConstraint(activation, columnInfo[ix].name, false); } } else if (columnInfo[ix].action == ColumnInfo.DROP) { dropColumnFromTable(activation, ix); } else if (SanityManager.DEBUG) { SanityManager.THROWASSERT( "Unexpected action in AlterTableConstantAction"); } } } /* Create/Drop any constraints */ if (constraintActions != null) { for (int conIndex = 0; conIndex < constraintActions.length; conIndex++) { ConstraintConstantAction cca = constraintActions[conIndex]; if (cca instanceof CreateConstraintConstantAction) { int constraintType = cca.getConstraintType(); /* Some constraint types require special checking: * Check - table must be empty, for now * Primary Key - table cannot already have a primary key */ switch (constraintType) { case DataDictionary.PRIMARYKEY_CONSTRAINT: // Check to see if a constraint of the same type already exists ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td); if (cdl.getPrimaryKey() != null) { throw StandardException.newException(SQLState.LANG_ADD_PRIMARY_KEY_FAILED1, td.getQualifiedName()); } if (! tableScanned) { tableScanned = true; numRows = getSemiRowCount(tc); } break; case DataDictionary.CHECK_CONSTRAINT: if (! tableScanned) { tableScanned = true; numRows = getSemiRowCount(tc); } if (numRows > 0) { /* ** We are assuming that there will only be one ** check constraint that we are adding, so it ** is ok to do the check now rather than try ** to lump together several checks. */ ConstraintConstantAction.validateConstraint( cca.getConstraintName(), ((CreateConstraintConstantAction)cca).getConstraintText(), td, lcc, true); } break; } } else { if (SanityManager.DEBUG) { if (!(cca instanceof DropConstraintConstantAction)) { SanityManager.THROWASSERT("constraintActions[" + conIndex + "] expected to be instanceof DropConstraintConstantAction not " + cca.getClass().getName()); } } } constraintActions[conIndex].executeConstantAction(activation); } } // Are we changing the lock granularity? if (lockGranularity != '\0') { if (SanityManager.DEBUG) { if (lockGranularity != 'T' && lockGranularity != 'R') { SanityManager.THROWASSERT( "lockGranularity expected to be 'T'or 'R', not " + lockGranularity); } } // update the TableDescriptor td.setLockGranularity(lockGranularity); // update the DataDictionary dd.updateLockGranularity(td, sd, lockGranularity, tc); } // Are we doing a compress table? if (compressTable) { compressTable(activation); } // Are we doing a truncate table? if (truncateTable) { truncateTable(activation); } } /** * Workhorse for adding a new column to a table. * * @param dd the data dictionary. * @param ix the index of the column specfication in the ALTER * statement-- currently we allow only one. * @exception StandardException thrown on failure. */ private void addNewColumnToTable(Activation activation, int ix) throws StandardException { LanguageConnectionContext lcc = activation.getLanguageConnectionContext(); DataDictionary dd = lcc.getDataDictionary(); DependencyManager dm = dd.getDependencyManager(); TransactionController tc = lcc.getTransactionExecute(); ColumnDescriptor columnDescriptor = td.getColumnDescriptor(columnInfo[ix].name); DataValueDescriptor storableDV; int colNumber = td.getMaxColumnID() + ix; DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator(); /* We need to verify that the table does not have an existing * column with the same name before we try to add the new * one as addColumnDescriptor() is a void method. */ if (columnDescriptor != null) { throw StandardException.newException( SQLState.LANG_OBJECT_ALREADY_EXISTS_IN_OBJECT, columnDescriptor.getDescriptorType(), columnInfo[ix].name, td.getDescriptorType(), td.getQualifiedName()); } if (columnInfo[ix].defaultValue != null) storableDV = columnInfo[ix].defaultValue; else storableDV = columnInfo[ix].dataType.getNull(); // Add the column to the conglomerate.(Column ids in store are 0-based) tc.addColumnToConglomerate(td.getHeapConglomerateId(), colNumber, storableDV); UUID defaultUUID = columnInfo[ix].newDefaultUUID; /* Generate a UUID for the default, if one exists * and there is no default id yet. */ if (columnInfo[ix].defaultInfo != null && defaultUUID == null) { defaultUUID = dd.getUUIDFactory().createUUID(); } // Add the column to syscolumns. // Column ids in system tables are 1-based columnDescriptor = new ColumnDescriptor( columnInfo[ix].name, colNumber + 1, columnInfo[ix].dataType, columnInfo[ix].defaultValue, columnInfo[ix].defaultInfo, td, defaultUUID, columnInfo[ix].autoincStart, columnInfo[ix].autoincInc ); dd.addDescriptor(columnDescriptor, td, DataDictionary.SYSCOLUMNS_CATALOG_NUM, false, tc); // now add the column to the tables column descriptor list. td.getColumnDescriptorList().add(columnDescriptor); if (columnDescriptor.isAutoincrement()) { updateNewAutoincrementColumn(activation, columnInfo[ix].name, columnInfo[ix].autoincStart, columnInfo[ix].autoincInc); } // Update the new column to its default, if it has a non-null default if (columnDescriptor.hasNonNullDefault()) { updateNewColumnToDefault(activation, columnInfo[ix].name, columnInfo[ix].defaultInfo.getDefaultText(), lcc); } } /** * Workhorse for dropping a column from a table. * * @param dd the data dictionary. * @param ix the index of the column specfication in the ALTER * statement-- currently we allow only one. * @exception StandardException thrown on failure. */ private void dropColumnFromTable(Activation activation, int ix) throws StandardException { LanguageConnectionContext lcc = activation.getLanguageConnectionContext(); DataDictionary dd = lcc.getDataDictionary(); DependencyManager dm = dd.getDependencyManager(); TransactionController tc = lcc.getTransactionExecute(); ColumnDescriptor columnDescriptor = td.getColumnDescriptor(columnInfo[ix].name); // We already verified this in bind, but do it again if (columnDescriptor == null) { throw StandardException.newException( SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, columnInfo[ix].name, td.getQualifiedName()); } DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator(); ColumnDescriptorList tab_cdl = td.getColumnDescriptorList(); int size = tab_cdl.size(); // can NOT drop a column if it is the only one in the table if (size == 1) { throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT, dm.getActionString(DependencyManager.DROP_COLUMN), "THE *LAST* COLUMN " + columnInfo[ix].name, "TABLE", td.getQualifiedName() ); } columnPosition = columnDescriptor.getPosition(); boolean cascade = (behavior == StatementType.DROP_CASCADE); FormatableBitSet toDrop = new FormatableBitSet(size + 1); toDrop.set(columnPosition); td.setReferencedColumnMap(toDrop); dm.invalidateFor(td, cascade ? DependencyManager.DROP_COLUMN_CASCADE : DependencyManager.DROP_COLUMN, lcc); // If column has a default we drop the default and any dependencies if (columnDescriptor.getDefaultInfo() != null) { DefaultDescriptor defaultDesc = columnDescriptor.getDefaultDescriptor(dd); dm.clearDependencies(lcc, defaultDesc); } // need to deal with triggers if has referencedColumns GenericDescriptorList tdl = dd.getTriggerDescriptors(td); Enumeration descs = tdl.elements(); while (descs.hasMoreElements()) { TriggerDescriptor trd = (TriggerDescriptor) descs.nextElement(); int[] referencedCols = trd.getReferencedCols(); if (referencedCols == null) continue; int refColLen = referencedCols.length, j; boolean changed = false; for (j = 0; j < refColLen; j++) { if (referencedCols[j] > columnPosition) changed = true; else if (referencedCols[j] == columnPosition) { if (cascade) { DropTriggerConstantAction.dropTriggerDescriptor(lcc, dm, dd, tc, trd, activation); activation.addWarning( StandardException.newWarning(SQLState.LANG_TRIGGER_DROPPED, trd.getName(), td.getName())); } else { // we'd better give an error if don't drop it, // otherwsie there would be unexpected behaviors throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT, dm.getActionString(DependencyManager.DROP_COLUMN), columnInfo[ix].name, "TRIGGER", trd.getName() ); } break; } } // change triggers to refer to columns in new positions if (j == refColLen && changed) { dd.dropTriggerDescriptor(trd, tc); for (j = 0; j < refColLen; j++) { if (referencedCols[j] > columnPosition) referencedCols[j]--; } dd.addDescriptor(trd, sd, DataDictionary.SYSTRIGGERS_CATALOG_NUM, false, tc); } } ConstraintDescriptorList csdl = dd.getConstraintDescriptors(td); int csdl_size = csdl.size(); // we want to remove referenced primary/unique keys in the second // round. This will ensure that self-referential constraints will // work OK. int tbr_size = 0; ConstraintDescriptor[] toBeRemoved = new ConstraintDescriptor[csdl_size]; // let's go downwards, don't want to get messed up while removing for (int i = csdl_size - 1; i >= 0; i--) { ConstraintDescriptor cd = csdl.elementAt(i); int[] referencedColumns = cd.getReferencedColumns(); int numRefCols = referencedColumns.length, j; boolean changed = false; for (j = 0; j < numRefCols; j++) { if (referencedColumns[j] > columnPosition) changed = true; if (referencedColumns[j] == columnPosition) break; } if (j == numRefCols) // column not referenced { if ((cd instanceof CheckConstraintDescriptor) && changed) { dd.dropConstraintDescriptor(td, cd, tc); for (j = 0; j < numRefCols; j++) { if (referencedColumns[j] > columnPosition) referencedColumns[j]--; } ((CheckConstraintDescriptor) cd).setReferencedColumnsDescriptor(new ReferencedColumnsDescriptorImpl(referencedColumns)); dd.addConstraintDescriptor(cd, tc); } continue; } if (! cascade) { if (numRefCols > 1 || cd.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT) { throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT, dm.getActionString(DependencyManager.DROP_COLUMN), columnInfo[ix].name, "CONSTRAINT", cd.getConstraintName() ); } } if (cd instanceof ReferencedKeyConstraintDescriptor) { // restrict will raise an error in invalidate if really referenced toBeRemoved[tbr_size++] = cd; continue; } // drop now in all other cases dm.invalidateFor(cd, DependencyManager.DROP_CONSTRAINT, lcc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -