use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor in project derby by apache.
the class ConsistencyChecker method checkTable.
/**
* Check the named table, ensuring that all of its indexes are consistent
* with the base table.
* Use this
* method only within an SQL-J statement; do not call it directly.
* <P>When tables are consistent, the method returns true. Otherwise, the method throws an exception.
* <p>To check the consistency of a single table:
* <p><code>
* VALUES ConsistencyChecker::checkTable(<i>SchemaName</i>, <i>TableName</i>)</code></p>
* <P>For example, to check the consistency of the table <i>APP.Flights</i>:
* <p><code>
* VALUES ConsistencyChecker::checkTable('APP', 'FLIGHTS')</code></p>
* <p>To check the consistency of all of the tables in the 'APP' schema,
* stopping at the first failure:
*
* <P><code>SELECT tablename, ConsistencyChecker::checkTable(<br>
* 'APP', tablename)<br>
* FROM sys.sysschemas s, sys.systables t
* WHERE s.schemaname = 'APP' AND s.schemaid = t.schemaid</code>
*
* <p> To check the consistency of an entire database, stopping at the first failure:
*
* <p><code>SELECT schemaname, tablename,<br>
* ConsistencyChecker::checkTable(schemaname, tablename)<br>
* FROM sys.sysschemas s, sys.systables t<br>
* WHERE s.schemaid = t.schemaid</code>
*
* @param schemaName The schema name of the table.
* @param tableName The name of the table
*
* @return true, if the table is consistent, exception thrown if inconsistent
*
* @exception SQLException Thrown if some inconsistency
* is found, or if some unexpected
* exception is thrown..
*/
public static boolean checkTable(String schemaName, String tableName) throws SQLException {
DataDictionary dd;
TableDescriptor td;
long baseRowCount = -1;
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;
SchemaDescriptor sd;
ConstraintDescriptor constraintDesc;
LanguageConnectionContext lcc = ConnectionUtil.getCurrentLCC();
tc = lcc.getTransactionExecute();
try {
// make sure that application code doesn't bypass security checks
// by calling this public entry point
SecurityUtil.authorize(Securable.CHECK_TABLE);
dd = lcc.getDataDictionary();
dvf = lcc.getDataValueFactory();
ExecutionFactory ef = lcc.getLanguageConnectionFactory().getExecutionFactory();
sd = dd.getSchemaDescriptor(schemaName, tc, true);
td = dd.getTableDescriptor(tableName, sd, tc);
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 = ef.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 (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(), // hold
false, // not forUpdate
0, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE, RowUtil.EMPTY_ROW_BITSET, // startKeyValue
null, // not used with null start posn.
0, // qualifier
null, // stopKeyValue
null, // not used with null stop posn.
0);
/* 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 = ef.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(), // hold
false, // not forUpdate
0, TransactionController.MODE_TABLE, TransactionController.ISOLATION_SERIALIZABLE, (FormatableBitSet) null, // startKeyValue
null, // not used with null start posn.
0, // qualifier
null, // stopKeyValue
null, // not used with null stop posn.
0);
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]);
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());
}
}
}
/* Clean up after the index scan */
scan.close();
scan = null;
/*
** The index is supposed to have the same number of rows as the
** base conglomerate.
*/
if (indexRows != baseRowCount) {
throw StandardException.newException(SQLState.LANG_INDEX_ROW_COUNT_MISMATCH, indexCD.getConglomerateName(), td.getSchemaName(), td.getName(), Long.toString(indexRows), Long.toString(baseRowCount));
}
}
/* check that all constraints have backing index */
ConstraintDescriptorList constraintDescList = dd.getConstraintDescriptors(td);
for (int index = 0; index < constraintDescList.size(); index++) {
constraintDesc = constraintDescList.elementAt(index);
if (constraintDesc.hasBackingIndex()) {
ConglomerateDescriptor conglomDesc;
conglomDesc = td.getConglomerateDescriptor(constraintDesc.getConglomerateId());
if (conglomDesc == null) {
throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, "INDEX for CONSTRAINT", constraintDesc.getConstraintName());
}
}
}
} catch (StandardException se) {
throw PublicAPI.wrapStandardException(se);
} finally {
try {
/* Clean up before we leave */
if (baseCC != null) {
baseCC.close();
baseCC = null;
}
if (indexCC != null) {
indexCC.close();
indexCC = null;
}
if (scan != null) {
scan.close();
scan = null;
}
} catch (StandardException se) {
throw PublicAPI.wrapStandardException(se);
}
}
return true;
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor in project derby by apache.
the class DataDictionaryImpl method getConstraintDescriptorViaHeap.
/**
* Return a (single or list of) catalog row descriptor(s) from
* SYSCONSTRAINTS through a heap scan
*
* @param scanQualifiers qualifiers
* @param ti The TabInfoImpl to use
* @param parentTupleDescriptor The parentDescriptor, if applicable.
* @param list The list to build, if supplied.
* If null, then caller expects a single descriptor
*
* @return The last matching descriptor
*
* @exception StandardException Thrown on error
*/
protected TupleDescriptor getConstraintDescriptorViaHeap(ScanQualifier[][] scanQualifiers, TabInfoImpl ti, TupleDescriptor parentTupleDescriptor, ConstraintDescriptorList list) throws StandardException {
SYSCONSTRAINTSRowFactory rf = (SYSCONSTRAINTSRowFactory) ti.getCatalogRowFactory();
ExecRow outRow;
ScanController scanController;
TransactionController tc;
ConstraintDescriptor cd = null;
// Get the current transaction controller
tc = getTransactionCompile();
outRow = rf.makeEmptyRow();
/*
** Table scan
*/
scanController = tc.openScan(// conglomerate to open
ti.getHeapConglomerate(), // don't hold open across commit
false, // for read
0, TransactionController.MODE_TABLE, TransactionController.ISOLATION_REPEATABLE_READ, // all fields as objects
(FormatableBitSet) null, // start position - first row
(DataValueDescriptor[]) null, // startSearchOperation - none
0, // scanQualifier,
scanQualifiers, // stop position -through last row
(DataValueDescriptor[]) null, // stopSearchOperation - none
0);
try {
while (scanController.fetchNext(outRow.getRowArray())) {
SubConstraintDescriptor subCD = null;
switch(rf.getConstraintType(outRow)) {
case DataDictionary.PRIMARYKEY_CONSTRAINT:
case DataDictionary.FOREIGNKEY_CONSTRAINT:
case DataDictionary.UNIQUE_CONSTRAINT:
subCD = getSubKeyConstraint(rf.getConstraintId(outRow), rf.getConstraintType(outRow));
break;
case DataDictionary.CHECK_CONSTRAINT:
subCD = getSubCheckConstraint(rf.getConstraintId(outRow));
break;
default:
if (SanityManager.DEBUG) {
SanityManager.THROWASSERT("unexpected value from " + " rf.getConstraintType(outRow) " + rf.getConstraintType(outRow));
}
}
if (SanityManager.DEBUG) {
SanityManager.ASSERT(subCD != null, "subCD is expected to be non-null");
}
cd = (ConstraintDescriptor) rf.buildDescriptor(outRow, subCD, this);
/* If dList is null, then caller only wants a single descriptor - we're done
* else just add the current descriptor to the list.
*/
if (list == null) {
break;
} else {
list.add(cd);
}
}
} finally {
scanController.close();
}
return cd;
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor in project derby by apache.
the class DataDictionaryImpl method getConstraintDescriptorViaIndex.
/**
* Return a (single or list of) ConstraintDescriptor(s) from
* SYSCONSTRAINTS where the access is from the index to the heap.
*
* @param indexId The id of the index (0 to # of indexes on table) to use
* @param keyRow The supplied ExecIndexRow for search
* @param ti The TabInfoImpl to use
* @param td The TableDescriptor, if supplied.
* @param dList The list to build, if supplied. If null, then caller expects
* a single descriptor
* @param forUpdate Whether or not to open scan for update
*
* @return The last matching descriptor
*
* @exception StandardException Thrown on error
*/
protected ConstraintDescriptor getConstraintDescriptorViaIndex(int indexId, ExecIndexRow keyRow, TabInfoImpl ti, TableDescriptor td, ConstraintDescriptorList dList, boolean forUpdate) throws StandardException {
SYSCONSTRAINTSRowFactory rf = (SYSCONSTRAINTSRowFactory) ti.getCatalogRowFactory();
ConglomerateController heapCC;
ConstraintDescriptor cd = null;
ExecIndexRow indexRow1;
ExecRow outRow;
RowLocation baseRowLocation;
ScanController scanController;
TransactionController tc;
// Get the current transaction controller
tc = getTransactionCompile();
outRow = rf.makeEmptyRow();
heapCC = tc.openConglomerate(ti.getHeapConglomerate(), false, 0, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ);
/* Scan the index and go to the data pages for qualifying rows to
* build the column descriptor.
*/
scanController = tc.openScan(// conglomerate to open
ti.getIndexConglomerate(indexId), // don't hold open across commit
false, (forUpdate) ? TransactionController.OPENMODE_FORUPDATE : 0, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ, // all fields as objects
(FormatableBitSet) null, // start position - exact key match.
keyRow.getRowArray(), // startSearchOperation
ScanController.GE, // scanQualifier,
null, // stop position - exact key match.
keyRow.getRowArray(), // stopSearchOperation
ScanController.GT);
while (scanController.next()) {
SubConstraintDescriptor subCD = null;
// create an index row template
indexRow1 = getIndexRowFromHeapRow(ti.getIndexRowGenerator(indexId), heapCC.newRowLocationTemplate(), outRow);
scanController.fetch(indexRow1.getRowArray());
baseRowLocation = (RowLocation) indexRow1.getColumn(indexRow1.nColumns());
boolean base_row_exists = heapCC.fetch(baseRowLocation, outRow.getRowArray(), (FormatableBitSet) null);
if (SanityManager.DEBUG) {
// it can not be possible for heap row to disappear while
// holding scan cursor on index at ISOLATION_REPEATABLE_READ.
SanityManager.ASSERT(base_row_exists, "base row doesn't exist");
}
switch(rf.getConstraintType(outRow)) {
case DataDictionary.PRIMARYKEY_CONSTRAINT:
case DataDictionary.FOREIGNKEY_CONSTRAINT:
case DataDictionary.UNIQUE_CONSTRAINT:
subCD = getSubKeyConstraint(rf.getConstraintId(outRow), rf.getConstraintType(outRow));
break;
case DataDictionary.CHECK_CONSTRAINT:
subCD = getSubCheckConstraint(rf.getConstraintId(outRow));
break;
default:
if (SanityManager.DEBUG) {
SanityManager.THROWASSERT("unexpected value " + "from rf.getConstraintType(outRow)" + rf.getConstraintType(outRow));
}
}
if (SanityManager.DEBUG) {
SanityManager.ASSERT(subCD != null, "subCD is expected to be non-null");
}
/* Cache the TD in the SCD so that
* the row factory doesn't need to go
* out to disk to get it.
*/
subCD.setTableDescriptor(td);
cd = (ConstraintDescriptor) rf.buildDescriptor(outRow, subCD, this);
/* If dList is null, then caller only wants a single descriptor - we're done
* else just add the current descriptor to the list.
*/
if (dList == null) {
break;
} else {
dList.add(cd);
}
}
scanController.close();
heapCC.close();
return cd;
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor in project derby by apache.
the class SYSCONSTRAINTSRowFactory method makeRow.
// ///////////////////////////////////////////////////////////////////////////
//
// METHODS
//
// ///////////////////////////////////////////////////////////////////////////
/**
* Make a SYSCONTRAINTS row
*
* @return Row suitable for inserting into SYSCONTRAINTS.
*
* @exception StandardException thrown on failure
*/
public ExecRow makeRow(TupleDescriptor td, TupleDescriptor parent) throws StandardException {
DataValueDescriptor col;
ExecRow row;
int constraintIType;
UUID oid;
String constraintSType = null;
String constraintID = null;
String tableID = null;
String constraintName = null;
String schemaID = null;
boolean deferrable = ConstraintDefinitionNode.DEFERRABLE_DEFAULT;
boolean initiallyDeferred = ConstraintDefinitionNode.INITIALLY_DEFERRED_DEFAULT;
boolean enforced = ConstraintDefinitionNode.ENFORCED_DEFAULT;
int referenceCount = 0;
if (td != null) {
ConstraintDescriptor constraint = (ConstraintDescriptor) td;
/*
** We only allocate a new UUID if the descriptor doesn't already have one.
** For descriptors replicated from a Source system, we already have an UUID.
*/
oid = constraint.getUUID();
constraintID = oid.toString();
oid = constraint.getTableId();
tableID = oid.toString();
constraintName = constraint.getConstraintName();
constraintIType = constraint.getConstraintType();
switch(constraintIType) {
case DataDictionary.PRIMARYKEY_CONSTRAINT:
constraintSType = "P";
break;
case DataDictionary.UNIQUE_CONSTRAINT:
constraintSType = "U";
break;
case DataDictionary.CHECK_CONSTRAINT:
constraintSType = "C";
break;
case DataDictionary.FOREIGNKEY_CONSTRAINT:
constraintSType = "F";
break;
default:
if (SanityManager.DEBUG) {
SanityManager.THROWASSERT("invalid constraint type");
}
}
schemaID = constraint.getSchemaDescriptor().getUUID().toString();
// constraint characteristics
deferrable = constraint.deferrable();
initiallyDeferred = constraint.initiallyDeferred();
enforced = constraint.enforced();
referenceCount = constraint.getReferenceCount();
}
/* Insert info into sysconstraints */
/* RESOLVE - It would be nice to require less knowledge about sysconstraints
* and have this be more table driven.
*/
/* Build the row to insert */
row = getExecutionFactory().getValueRow(SYSCONSTRAINTS_COLUMN_COUNT);
/* 1st column is CONSTRAINTID (UUID - char(36)) */
row.setColumn(SYSCONSTRAINTS_CONSTRAINTID, new SQLChar(constraintID));
/* 2nd column is TABLEID (UUID - char(36)) */
row.setColumn(SYSCONSTRAINTS_TABLEID, new SQLChar(tableID));
/* 3rd column is NAME (varchar(128)) */
row.setColumn(SYSCONSTRAINTS_CONSTRAINTNAME, new SQLVarchar(constraintName));
/* 4th column is TYPE (char(1)) */
row.setColumn(SYSCONSTRAINTS_TYPE, new SQLChar(constraintSType));
/* 5th column is SCHEMAID (UUID - char(36)) */
row.setColumn(SYSCONSTRAINTS_SCHEMAID, new SQLChar(schemaID));
/* 6th column is STATE (char(1)) */
row.setColumn(SYSCONSTRAINTS_STATE, new SQLChar(encodeCharacteristics(deferrable, initiallyDeferred, enforced)));
/* 7th column is REFERENCED */
row.setColumn(SYSCONSTRAINTS_REFERENCECOUNT, new SQLInteger(referenceCount));
return row;
}
use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor in project derby by apache.
the class AccessPathImpl method initializeAccessPathName.
/**
* @see AccessPath#initializeAccessPathName
*/
public void initializeAccessPathName(DataDictionary dd, TableDescriptor td) throws StandardException {
if (cd == null)
return;
if (cd.isConstraint()) {
ConstraintDescriptor constraintDesc = dd.getConstraintDescriptor(td, cd.getUUID());
if (constraintDesc == null) {
throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, "CONSTRAINT on TABLE", td.getName());
}
accessPathName = constraintDesc.getConstraintName();
} else if (cd.isIndex()) {
accessPathName = cd.getConglomerateName();
} else {
accessPathName = "";
}
}
Aggregations