use of org.apache.derby.iapi.services.io.FormatableBitSet 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.services.io.FormatableBitSet in project derby by apache.
the class StatementColumnPermission method check.
/**
* @see StatementPermission#check
*/
public void check(LanguageConnectionContext lcc, boolean forGrant, Activation activation) throws StandardException {
DataDictionary dd = lcc.getDataDictionary();
ExecPreparedStatement ps = activation.getPreparedStatement();
if (hasPermissionOnTable(lcc, activation, forGrant, ps)) {
return;
}
String currentUserId = lcc.getCurrentUserId(activation);
FormatableBitSet permittedColumns = null;
if (!forGrant) {
permittedColumns = addPermittedColumns(dd, false, /* non-grantable permissions */
Authorizer.PUBLIC_AUTHORIZATION_ID, permittedColumns);
permittedColumns = addPermittedColumns(dd, false, /* non-grantable permissions */
currentUserId, permittedColumns);
}
permittedColumns = addPermittedColumns(dd, true, /* grantable permissions */
Authorizer.PUBLIC_AUTHORIZATION_ID, permittedColumns);
permittedColumns = addPermittedColumns(dd, true, /* grantable permissions */
currentUserId, permittedColumns);
// select t1.c1 from t1, t2
if (privType == Authorizer.MIN_SELECT_PRIV && permittedColumns != null)
return;
FormatableBitSet unresolvedColumns = (FormatableBitSet) columns.clone();
for (int i = unresolvedColumns.anySetBit(); i >= 0; i = unresolvedColumns.anySetBit(i)) {
if (permittedColumns != null && permittedColumns.get(i)) {
// column i (zero-based here) accounted for:
unresolvedColumns.clear(i);
}
}
if (unresolvedColumns.anySetBit() < 0) {
// all ok
return;
}
// If columns are still unauthorized, look to role closure for
// resolution.
String role = lcc.getCurrentRoleId(activation);
RoleGrantDescriptor rd = null;
if (role != null) {
// Check that role is still granted to current user or
// to PUBLIC: A revoked role which is current for this
// session, is lazily set to none when it is attempted
// used.
String dbo = dd.getAuthorizationDatabaseOwner();
rd = dd.getRoleGrantDescriptor(role, currentUserId, dbo);
if (rd == null) {
rd = dd.getRoleGrantDescriptor(role, Authorizer.PUBLIC_AUTHORIZATION_ID, dbo);
}
if (rd == null) {
// we have lost the right to set this role, so we can't
// make use of any permission granted to it or its ancestors.
lcc.setCurrentRole(activation, null);
} else {
// The current role is OK, so we can make use of
// any permission granted to it.
//
// Look at the current role and, if necessary, the transitive
// closure of roles granted to current role to see if
// permission has been granted to any of the applicable roles.
RoleClosureIterator rci = dd.createRoleClosureIterator(activation.getTransactionController(), role, true);
String r;
while (unresolvedColumns.anySetBit() >= 0 && (r = rci.next()) != null) {
// The user does not have needed privilege directly
// granted to it, so let's see if he has that privilege
// available to him/her through his roles.
permittedColumns = tryRole(lcc, dd, forGrant, r);
// select t1.c1 from t1, t2
if (privType == Authorizer.MIN_SELECT_PRIV && permittedColumns != null) {
DependencyManager dm = dd.getDependencyManager();
RoleGrantDescriptor rgd = dd.getRoleDefinitionDescriptor(role);
ContextManager cm = lcc.getContextManager();
dm.addDependency(ps, rgd, cm);
dm.addDependency(activation, rgd, cm);
return;
}
// we will quit out of this while loop
for (int i = unresolvedColumns.anySetBit(); i >= 0; i = unresolvedColumns.anySetBit(i)) {
if (permittedColumns != null && permittedColumns.get(i)) {
unresolvedColumns.clear(i);
}
}
}
}
}
TableDescriptor td = getTableDescriptor(dd);
// privilege on the table or any column in the table
if (privType == Authorizer.MIN_SELECT_PRIV)
throw StandardException.newException(forGrant ? SQLState.AUTH_NO_TABLE_PERMISSION_FOR_GRANT : SQLState.AUTH_NO_TABLE_PERMISSION, currentUserId, getPrivName(), td.getSchemaName(), td.getName());
int remains = unresolvedColumns.anySetBit();
if (remains >= 0) {
// No permission on this column.
ColumnDescriptor cd = td.getColumnDescriptor(remains + 1);
if (cd == null) {
throw StandardException.newException(SQLState.AUTH_INTERNAL_BAD_UUID, "column");
} else {
throw StandardException.newException((forGrant ? SQLState.AUTH_NO_COLUMN_PERMISSION_FOR_GRANT : SQLState.AUTH_NO_COLUMN_PERMISSION), currentUserId, getPrivName(), cd.getColumnName(), td.getSchemaName(), td.getName());
}
} else {
// We found and successfully applied a role to resolve the
// (remaining) required permissions.
//
// Also add a dependency on the role (qua provider), so
// that if role is no longer available to the current
// user (e.g. grant is revoked, role is dropped,
// another role has been set), we are able to
// invalidate the ps or activation (the latter is used
// if the current role changes).
DependencyManager dm = dd.getDependencyManager();
RoleGrantDescriptor rgd = dd.getRoleDefinitionDescriptor(role);
ContextManager cm = lcc.getContextManager();
dm.addDependency(ps, rgd, cm);
dm.addDependency(activation, rgd, cm);
}
}
use of org.apache.derby.iapi.services.io.FormatableBitSet in project derby by apache.
the class DataDictionaryImpl method getUUIDForCoreTable.
/**
* Get the UUID for the specified system table. Prior
* to Plato, system tables did not have canonical UUIDs, so
* we need to scan systables to get the UUID when we
* are updating the core tables.
*
* @param tableName Name of the table
* @param schemaUUID UUID of schema
* @param tc TransactionController to user
*
* @return UUID The UUID of the core table.
*
* @exception StandardException Thrown on failure
*/
private UUID getUUIDForCoreTable(String tableName, String schemaUUID, TransactionController tc) throws StandardException {
ConglomerateController heapCC;
ExecRow row;
DataValueDescriptor schemaIDOrderable;
DataValueDescriptor tableNameOrderable;
ScanController scanController;
TabInfoImpl ti = coreInfo[SYSTABLES_CORE_NUM];
SYSTABLESRowFactory rf = (SYSTABLESRowFactory) ti.getCatalogRowFactory();
// We only want the 1st column from the heap
row = exFactory.getValueRow(1);
/* Use tableNameOrderable and schemaIdOrderable in both start
* and stop position for scan.
*/
tableNameOrderable = new SQLVarchar(tableName);
schemaIDOrderable = new SQLChar(schemaUUID);
/* Set up the start/stop position for the scan */
ExecIndexRow keyRow = exFactory.getIndexableRow(2);
keyRow.setColumn(1, tableNameOrderable);
keyRow.setColumn(2, schemaIDOrderable);
heapCC = tc.openConglomerate(ti.getHeapConglomerate(), false, 0, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ);
ExecRow indexTemplateRow = rf.buildEmptyIndexRow(SYSTABLESRowFactory.SYSTABLES_INDEX1_ID, heapCC.newRowLocationTemplate());
/* 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(SYSTABLESRowFactory.SYSTABLES_INDEX1_ID), // don't hold open across commit
false, 0, TransactionController.MODE_RECORD, TransactionController.ISOLATION_REPEATABLE_READ, // all fields as objects
(FormatableBitSet) null, // start position - first row
keyRow.getRowArray(), // startSearchOperation
ScanController.GE, // scanQualifier,
(ScanQualifier[][]) null, // stop position - through last row
keyRow.getRowArray(), // stopSearchOperation
ScanController.GT);
/* OK to fetch into the template row,
* since we won't be doing a next.
*/
if (scanController.fetchNext(indexTemplateRow.getRowArray())) {
RowLocation baseRowLocation;
baseRowLocation = (RowLocation) indexTemplateRow.getColumn(indexTemplateRow.nColumns());
/* 1st column is TABLEID (UUID - char(36)) */
row.setColumn(SYSTABLESRowFactory.SYSTABLES_TABLEID, new SQLChar());
FormatableBitSet bi = new FormatableBitSet(1);
bi.set(0);
boolean base_row_exists = heapCC.fetch(baseRowLocation, row.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 not found");
}
}
scanController.close();
heapCC.close();
return uuidFactory.recreateUUID(row.getColumn(1).toString());
}
use of org.apache.derby.iapi.services.io.FormatableBitSet in project derby by apache.
the class DataDictionaryImpl method clearSPSPlans.
/**
* Mark all SPS plans in the data dictionary invalid. This does
* not invalidate cached plans. This function is for use by
* the boot-up code.
* @exception StandardException Thrown on error
*/
void clearSPSPlans() throws StandardException {
TabInfoImpl ti = getNonCoreTI(SYSSTATEMENTS_CATALOG_NUM);
faultInTabInfo(ti);
TransactionController tc = getTransactionExecute();
FormatableBitSet columnToReadSet = new FormatableBitSet(SYSSTATEMENTSRowFactory.SYSSTATEMENTS_COLUMN_COUNT);
FormatableBitSet columnToUpdateSet = new FormatableBitSet(SYSSTATEMENTSRowFactory.SYSSTATEMENTS_COLUMN_COUNT);
columnToUpdateSet.set(SYSSTATEMENTSRowFactory.SYSSTATEMENTS_VALID - 1);
columnToUpdateSet.set(SYSSTATEMENTSRowFactory.SYSSTATEMENTS_CONSTANTSTATE - 1);
DataValueDescriptor[] replaceRow = new DataValueDescriptor[SYSSTATEMENTSRowFactory.SYSSTATEMENTS_COLUMN_COUNT];
/* Set up a couple of row templates for fetching CHARS */
replaceRow[SYSSTATEMENTSRowFactory.SYSSTATEMENTS_VALID - 1] = new SQLBoolean(false);
replaceRow[SYSSTATEMENTSRowFactory.SYSSTATEMENTS_CONSTANTSTATE - 1] = new UserType((Object) null);
/* Scan the entire heap */
ScanController sc = tc.openScan(ti.getHeapConglomerate(), false, TransactionController.OPENMODE_FORUPDATE, TransactionController.MODE_TABLE, TransactionController.ISOLATION_REPEATABLE_READ, columnToReadSet, (DataValueDescriptor[]) null, ScanController.NA, (Qualifier[][]) null, (DataValueDescriptor[]) null, ScanController.NA);
while (sc.fetchNext((DataValueDescriptor[]) null)) {
/* Replace the column in the table */
sc.replace(replaceRow, columnToUpdateSet);
}
sc.close();
}
use of org.apache.derby.iapi.services.io.FormatableBitSet in project derby by apache.
the class DataDictionaryImpl method getDescriptorViaIndexMinion.
private <T extends TupleDescriptor> T getDescriptorViaIndexMinion(int indexId, ExecIndexRow keyRow, ScanQualifier[][] scanQualifiers, TabInfoImpl ti, TupleDescriptor parentTupleDescriptor, List<? super T> list, Class<T> returnType, boolean forUpdate, int isolationLevel, TransactionController tc) throws StandardException {
CatalogRowFactory rf = ti.getCatalogRowFactory();
ConglomerateController heapCC;
ExecIndexRow indexRow1;
ExecRow outRow;
RowLocation baseRowLocation;
ScanController scanController;
T td = null;
if (SanityManager.DEBUG) {
SanityManager.ASSERT(isolationLevel == TransactionController.ISOLATION_REPEATABLE_READ || isolationLevel == TransactionController.ISOLATION_READ_UNCOMMITTED);
}
outRow = rf.makeEmptyRow();
heapCC = tc.openConglomerate(ti.getHeapConglomerate(), false, 0, TransactionController.MODE_RECORD, isolationLevel);
/* 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, isolationLevel, // all fields as objects
(FormatableBitSet) null, // start position - first row
keyRow.getRowArray(), // startSearchOperation
ScanController.GE, // scanQualifier,
scanQualifiers, // stop position - through last row
keyRow.getRowArray(), // stopSearchOperation
ScanController.GT);
while (true) {
// create an index row template
indexRow1 = getIndexRowFromHeapRow(ti.getIndexRowGenerator(indexId), heapCC.newRowLocationTemplate(), outRow);
// from the table.
if (!scanController.fetchNext(indexRow1.getRowArray())) {
break;
}
baseRowLocation = (RowLocation) indexRow1.getColumn(indexRow1.nColumns());
// RESOLVE paulat - remove the try catch block when track 3677 is fixed
// just leave the contents of the try block
// adding to get more info on track 3677
boolean base_row_exists = false;
try {
base_row_exists = heapCC.fetch(baseRowLocation, outRow.getRowArray(), (FormatableBitSet) null);
} catch (RuntimeException re) {
if (SanityManager.DEBUG) {
if (re instanceof AssertFailure) {
StringBuffer strbuf = new StringBuffer("Error retrieving base row in table " + ti.getTableName());
strbuf.append(": An ASSERT was thrown when trying to locate a row matching index row " + indexRow1 + " from index " + ti.getIndexName(indexId) + ", conglom number " + ti.getIndexConglomerate(indexId));
debugGenerateInfo(strbuf, tc, heapCC, ti, indexId);
}
}
throw re;
} catch (StandardException se) {
if (SanityManager.DEBUG) {
// do not want to catch lock timeout errors here
if (se.getSQLState().equals("XSRS9")) {
StringBuffer strbuf = new StringBuffer("Error retrieving base row in table " + ti.getTableName());
strbuf.append(": A StandardException was thrown when trying to locate a row matching index row " + indexRow1 + " from index " + ti.getIndexName(indexId) + ", conglom number " + ti.getIndexConglomerate(indexId));
debugGenerateInfo(strbuf, tc, heapCC, ti, indexId);
}
}
throw se;
}
if (SanityManager.DEBUG) {
// holding scan cursor on index at ISOLATION_REPEATABLE_READ.
if (!base_row_exists && (isolationLevel == TransactionController.ISOLATION_REPEATABLE_READ)) {
StringBuffer strbuf = new StringBuffer("Error retrieving base row in table " + ti.getTableName());
strbuf.append(": could not locate a row matching index row " + indexRow1 + " from index " + ti.getIndexName(indexId) + ", conglom number " + ti.getIndexConglomerate(indexId));
debugGenerateInfo(strbuf, tc, heapCC, ti, indexId);
// RESOLVE: for now, we are going to kill the VM
// to help debug this problem.
System.exit(1);
// RESOLVE: not currently reached
// SanityManager.THROWASSERT(strbuf.toString());
}
}
if (!base_row_exists && (isolationLevel == TransactionController.ISOLATION_READ_UNCOMMITTED)) {
// If isolationLevel == ISOLATION_READ_UNCOMMITTED we may
// possibly see that the base row does not exist even if the
// index row did. This mode is currently only used by
// TableNameInfo's call to hashAllTableDescriptorsByTableId,
// cf. DERBY-3678, and by getStatisticsDescriptors,
// cf. DERBY-4881.
//
// For the former call, a table's schema descriptor is attempted
// read, and if the base row for the schema has gone between
// reading the index and the base table, the table that needs
// this information has gone, too. So, the table should not
// be needed for printing lock timeout or deadlock
// information, so we can safely just return an empty (schema)
// descriptor. Furthermore, neither Timeout or DeadLock
// diagnostics access the schema of a table descriptor, so it
// seems safe to just return an empty schema descriptor for
// the table.
//
// There is a theoretical chance another row may have taken
// the first one's place, but only if a compress of the base
// table managed to run between the time we read the index and
// the base row, which seems unlikely so we ignore that.
//
// Even the index row may be gone in the above use case, of
// course, and that case also returns an empty descriptor
// since no match is found.
td = null;
} else {
// normal case
td = returnType.cast(rf.buildDescriptor(outRow, parentTupleDescriptor, this));
}
/* If list 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 if (td != null) {
list.add(td);
}
}
scanController.close();
heapCC.close();
return td;
}
Aggregations