Search in sources :

Example 1 with FormatableBitSet

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;
}
Also used : ConglomerateController(org.apache.derby.iapi.store.access.ConglomerateController) StandardException(org.apache.derby.shared.common.error.StandardException) ColumnDescriptorList(org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList) DataValueFactory(org.apache.derby.iapi.types.DataValueFactory) FormatableBitSet(org.apache.derby.iapi.services.io.FormatableBitSet) RowLocation(org.apache.derby.iapi.types.RowLocation) ScanController(org.apache.derby.iapi.store.access.ScanController) SchemaDescriptor(org.apache.derby.iapi.sql.dictionary.SchemaDescriptor) ColumnDescriptor(org.apache.derby.iapi.sql.dictionary.ColumnDescriptor) ExecutionFactory(org.apache.derby.iapi.sql.execute.ExecutionFactory) ConstraintDescriptorList(org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList) DataDictionary(org.apache.derby.iapi.sql.dictionary.DataDictionary) ConglomerateDescriptor(org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor) TableDescriptor(org.apache.derby.iapi.sql.dictionary.TableDescriptor) LanguageConnectionContext(org.apache.derby.iapi.sql.conn.LanguageConnectionContext) ConstraintDescriptor(org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor) ExecRow(org.apache.derby.iapi.sql.execute.ExecRow) DataValueDescriptor(org.apache.derby.iapi.types.DataValueDescriptor) TransactionController(org.apache.derby.iapi.store.access.TransactionController)

Example 2 with FormatableBitSet

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);
    }
}
Also used : ExecPreparedStatement(org.apache.derby.iapi.sql.execute.ExecPreparedStatement) ContextManager(org.apache.derby.iapi.services.context.ContextManager) DependencyManager(org.apache.derby.iapi.sql.depend.DependencyManager) FormatableBitSet(org.apache.derby.iapi.services.io.FormatableBitSet)

Example 3 with FormatableBitSet

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());
}
Also used : ScanController(org.apache.derby.iapi.store.access.ScanController) ConglomerateController(org.apache.derby.iapi.store.access.ConglomerateController) SQLChar(org.apache.derby.iapi.types.SQLChar) SQLVarchar(org.apache.derby.iapi.types.SQLVarchar) ExecIndexRow(org.apache.derby.iapi.sql.execute.ExecIndexRow) ExecRow(org.apache.derby.iapi.sql.execute.ExecRow) ScanQualifier(org.apache.derby.iapi.sql.execute.ScanQualifier) FormatableBitSet(org.apache.derby.iapi.services.io.FormatableBitSet) DataValueDescriptor(org.apache.derby.iapi.types.DataValueDescriptor) RowLocation(org.apache.derby.iapi.types.RowLocation)

Example 4 with FormatableBitSet

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();
}
Also used : ScanController(org.apache.derby.iapi.store.access.ScanController) FormatableBitSet(org.apache.derby.iapi.services.io.FormatableBitSet) DataValueDescriptor(org.apache.derby.iapi.types.DataValueDescriptor) TransactionController(org.apache.derby.iapi.store.access.TransactionController) UserType(org.apache.derby.iapi.types.UserType) SQLBoolean(org.apache.derby.iapi.types.SQLBoolean)

Example 5 with FormatableBitSet

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;
}
Also used : ScanController(org.apache.derby.iapi.store.access.ScanController) ConglomerateController(org.apache.derby.iapi.store.access.ConglomerateController) CatalogRowFactory(org.apache.derby.iapi.sql.dictionary.CatalogRowFactory) ExecIndexRow(org.apache.derby.iapi.sql.execute.ExecIndexRow) StandardException(org.apache.derby.shared.common.error.StandardException) ExecRow(org.apache.derby.iapi.sql.execute.ExecRow) FormatableBitSet(org.apache.derby.iapi.services.io.FormatableBitSet) AssertFailure(org.apache.derby.shared.common.sanity.AssertFailure) RowLocation(org.apache.derby.iapi.types.RowLocation)

Aggregations

FormatableBitSet (org.apache.derby.iapi.services.io.FormatableBitSet)146 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)36 RowLocation (org.apache.derby.iapi.types.RowLocation)32 SQLLongint (org.apache.derby.iapi.types.SQLLongint)25 ScanController (org.apache.derby.iapi.store.access.ScanController)24 ExecRow (org.apache.derby.iapi.sql.execute.ExecRow)23 ConglomerateController (org.apache.derby.iapi.store.access.ConglomerateController)18 StandardException (org.apache.derby.shared.common.error.StandardException)17 RawTransaction (org.apache.derby.iapi.store.raw.xact.RawTransaction)15 RawContainerHandle (org.apache.derby.iapi.store.raw.data.RawContainerHandle)13 TransactionController (org.apache.derby.iapi.store.access.TransactionController)12 ConglomerateDescriptor (org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)11 SQLInteger (org.apache.derby.iapi.types.SQLInteger)11 UUID (org.apache.derby.catalog.UUID)10 ExecIndexRow (org.apache.derby.iapi.sql.execute.ExecIndexRow)10 ConstraintDescriptor (org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor)9 DataDictionary (org.apache.derby.iapi.sql.dictionary.DataDictionary)7 SQLChar (org.apache.derby.iapi.types.SQLChar)7 Properties (java.util.Properties)6 ContextManager (org.apache.derby.iapi.services.context.ContextManager)6