TransactionController tc;
ConglomerateDescriptor heapCD;
ConglomerateDescriptor indexCD;
ExecRow baseRow;
ExecRow indexRow;
RowLocation rl = null;
RowLocation scanRL = null;
ScanController scan = null;
int[] baseColumnPositions;
int baseColumns = 0;
DataValueFactory dvf;
long indexRows;
ConglomerateController baseCC = null;
ConglomerateController indexCC = null;
ExecutionContext ec;
SchemaDescriptor sd;
ConstraintDescriptor constraintDesc;
LanguageConnectionContext lcc = ConnectionUtil.getCurrentLCC();
tc = lcc.getTransactionExecute();
try {
dd = lcc.getDataDictionary();
dvf = lcc.getDataValueFactory();
ec = lcc.getExecutionContext() ;
sd = dd.getSchemaDescriptor(schemaName, tc, true);
td = dd.getTableDescriptor(tableName, sd);
if (td == null)
{
throw StandardException.newException(
SQLState.LANG_TABLE_NOT_FOUND,
schemaName + "." + tableName);
}
/* Skip views */
if (td.getTableType() == TableDescriptor.VIEW_TYPE)
{
return true;
}
/* Open the heap for reading */
baseCC = tc.openConglomerate(
td.getHeapConglomerateId(), false, 0,
TransactionController.MODE_TABLE,
TransactionController.ISOLATION_SERIALIZABLE);
/* Check the consistency of the heap */
baseCC.checkConsistency();
heapCD = td.getConglomerateDescriptor(td.getHeapConglomerateId());
/* Get a row template for the base table */
baseRow = ec.getExecutionFactory().getValueRow(td.getNumberOfColumns());
/* Fill the row with nulls of the correct type */
ColumnDescriptorList cdl = td.getColumnDescriptorList();
int cdlSize = cdl.size();
for (int index = 0; index < cdlSize; index++)
{
ColumnDescriptor cd = (ColumnDescriptor) cdl.elementAt(index);
baseRow.setColumn(cd.getPosition(),
cd.getType().getNull());
}
/* Look at all the indexes on the table */
ConglomerateDescriptor[] cds = td.getConglomerateDescriptors();
for (int index = 0; index < cds.length; index++)
{
indexCD = cds[index];
/* Skip the heap */
if ( ! indexCD.isIndex())
continue;
/* Check the internal consistency of the index */
indexCC =
tc.openConglomerate(
indexCD.getConglomerateNumber(),
false,
0,
TransactionController.MODE_TABLE,
TransactionController.ISOLATION_SERIALIZABLE);
indexCC.checkConsistency();
indexCC.close();
indexCC = null;
/* if index is for a constraint check that the constraint exists */
if (indexCD.isConstraint())
{
constraintDesc = dd.getConstraintDescriptor(td, indexCD.getUUID());
if (constraintDesc == null)
{
throw StandardException.newException(
SQLState.LANG_OBJECT_NOT_FOUND,
"CONSTRAINT for INDEX",
indexCD.getConglomerateName());
}
}
/*
** Set the base row count when we get to the first index.
** We do this here, rather than outside the index loop, so
** we won't do the work of counting the rows in the base table
** if there are no indexes to check.
*/
if (baseRowCount < 0)
{
scan = tc.openScan(heapCD.getConglomerateNumber(),
false, // hold
0, // not forUpdate
TransactionController.MODE_TABLE,
TransactionController.ISOLATION_SERIALIZABLE,
RowUtil.EMPTY_ROW_BITSET,
null, // startKeyValue
0, // not used with null start posn.
null, // qualifier
null, // stopKeyValue
0); // not used with null stop posn.
/* Also, get the row location template for index rows */
rl = scan.newRowLocationTemplate();
scanRL = scan.newRowLocationTemplate();
for (baseRowCount = 0; scan.next(); baseRowCount++)
; /* Empty statement */
scan.close();
scan = null;
}
baseColumnPositions =
indexCD.getIndexDescriptor().baseColumnPositions();
baseColumns = baseColumnPositions.length;
FormatableBitSet indexColsBitSet = new FormatableBitSet();
for (int i = 0; i < baseColumns; i++)
{
indexColsBitSet.grow(baseColumnPositions[i]);
indexColsBitSet.set(baseColumnPositions[i] - 1);
}
/* Get one row template for the index scan, and one for the fetch */
indexRow = ec.getExecutionFactory().getValueRow(baseColumns + 1);
/* Fill the row with nulls of the correct type */
for (int column = 0; column < baseColumns; column++)
{
/* Column positions in the data dictionary are one-based */
ColumnDescriptor cd = td.getColumnDescriptor(baseColumnPositions[column]);
indexRow.setColumn(column + 1,
cd.getType().getNull());
}
/* Set the row location in the last column of the index row */
indexRow.setColumn(baseColumns + 1, rl);
/* Do a full scan of the index */
scan = tc.openScan(indexCD.getConglomerateNumber(),
false, // hold
0, // not forUpdate
TransactionController.MODE_TABLE,
TransactionController.ISOLATION_SERIALIZABLE,
(FormatableBitSet) null,
null, // startKeyValue
0, // not used with null start posn.
null, // qualifier
null, // stopKeyValue
0); // not used with null stop posn.
DataValueDescriptor[] baseRowIndexOrder =
new DataValueDescriptor[baseColumns];
DataValueDescriptor[] baseObjectArray = baseRow.getRowArray();
for (int i = 0; i < baseColumns; i++)
{
baseRowIndexOrder[i] = baseObjectArray[baseColumnPositions[i] - 1];
}
/* Get the index rows and count them */
for (indexRows = 0; scan.fetchNext(indexRow.getRowArray()); indexRows++)
{
/*
** Get the base row using the RowLocation in the index row,
** which is in the last column.
*/
RowLocation baseRL = (RowLocation) indexRow.getColumn(baseColumns + 1);
boolean base_row_exists =
baseCC.fetch(
baseRL, baseObjectArray, indexColsBitSet);
/* Throw exception if fetch() returns false */
if (! base_row_exists)
{
String indexName = indexCD.getConglomerateName();
throw StandardException.newException(SQLState.LANG_INCONSISTENT_ROW_LOCATION,
(schemaName + "." + tableName),
indexName,
baseRL.toString(),
indexRow.toString());
}
/* Compare all the column values */
for (int column = 0; column < baseColumns; column++)
{
DataValueDescriptor indexColumn =
indexRow.getColumn(column + 1);
DataValueDescriptor baseColumn =
baseRowIndexOrder[column];
/*
** With this form of compare(), null is considered equal
** to null.
*/
if (indexColumn.compare(baseColumn) != 0)
{
ColumnDescriptor cd =
td.getColumnDescriptor(
baseColumnPositions[column]);
/*
System.out.println(
"SQLState.LANG_INDEX_COLUMN_NOT_EQUAL:" +
"indexCD.getConglomerateName()" + indexCD.getConglomerateName() +
";td.getSchemaName() = " + td.getSchemaName() +
";td.getName() = " + td.getName() +
";baseRL.toString() = " + baseRL.toString() +
";cd.getColumnName() = " + cd.getColumnName() +
";indexColumn.toString() = " + indexColumn.toString() +
";baseColumn.toString() = " + baseColumn.toString() +
";indexRow.toString() = " + indexRow.toString());
*/
throw StandardException.newException(
SQLState.LANG_INDEX_COLUMN_NOT_EQUAL,
indexCD.getConglomerateName(),
td.getSchemaName(),
td.getName(),
baseRL.toString(),
cd.getColumnName(),
indexColumn.toString(),
baseColumn.toString(),
indexRow.toString());
}