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, 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);
DropConstraintConstantAction.dropConstraintAndIndex(dm, td, dd,
cd, tc, lcc, true);
activation.addWarning(StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
cd.getConstraintName(), td.getName()));
}
for (int i = tbr_size - 1; i >= 0; i--)
{
ConstraintDescriptor cd = toBeRemoved[i];
DropConstraintConstantAction.dropConstraintAndIndex(dm, td, dd, cd,
tc, lcc, false);
activation.addWarning(StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
cd.getConstraintName(), td.getName()));
if (cascade)
{
ConstraintDescriptorList fkcdl = dd.getForeignKeys(cd.getUUID());
for (int j = 0; j < fkcdl.size(); j++)
{
ConstraintDescriptor fkcd = (ConstraintDescriptor) fkcdl.elementAt(j);
dm.invalidateFor(fkcd,
DependencyManager.DROP_CONSTRAINT,
lcc);
DropConstraintConstantAction.dropConstraintAndIndex(
dm, fkcd.getTableDescriptor(), dd, fkcd, tc, lcc, true);
activation.addWarning(StandardException.newWarning(SQLState.LANG_CONSTRAINT_DROPPED,
fkcd.getConstraintName(), fkcd.getTableDescriptor().getName()));
}
}
dm.invalidateFor(cd, DependencyManager.DROP_CONSTRAINT, lcc);
dm.clearDependencies(lcc, cd);
}
compressTable(activation);
// drop the column from syscolumns
dd.dropColumnDescriptor(td.getUUID(), columnInfo[ix].name, tc);
ColumnDescriptor[] cdlArray = new ColumnDescriptor[size - columnDescriptor.getPosition()];
for (int i = columnDescriptor.getPosition(), j = 0; i < size; i++, j++)
{
ColumnDescriptor cd = (ColumnDescriptor) tab_cdl.elementAt(i);
dd.dropColumnDescriptor(td.getUUID(), cd.getColumnName(), tc);
cd.setPosition(i);
cdlArray[j] = cd;
}
dd.addDescriptorArray(cdlArray, td,