Search in sources :

Example 1 with ConstraintDescriptorList

use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList 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 ConstraintDescriptorList

use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList in project derby by apache.

the class DataDictionaryImpl method getAllConstraintDescriptors.

/**
 * Get every constraint in this database.
 * Note that this list of ConstraintDescriptors is
 * not going to be the same objects that are typically
 * cached off of the table descriptors, so this will
 * most likely instantiate some duplicate objects.
 *
 * @return the list of descriptors
 *
 * @exception StandardException		Thrown on failure
 */
private ConstraintDescriptorList getAllConstraintDescriptors() throws StandardException {
    TabInfoImpl ti = getNonCoreTI(SYSCONSTRAINTS_CATALOG_NUM);
    ConstraintDescriptorList list = new ConstraintDescriptorList();
    getConstraintDescriptorViaHeap((ScanQualifier[][]) null, ti, (TupleDescriptor) null, list);
    return list;
}
Also used : ConstraintDescriptorList(org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList)

Example 3 with ConstraintDescriptorList

use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList in project derby by apache.

the class DataDictionaryImpl method getConstraintDescriptorsScan.

/**
 * Populate the ConstraintDescriptorList for the specified TableDescriptor.
 *
 * MT synchronization: it is assumed that the caller has synchronized
 * on the CDL in the given TD.
 *
 * @param td				The TableDescriptor.
 * @param forUpdate			Whether or not to open scan for update
 *
 * @exception StandardException		Thrown on failure
 */
private void getConstraintDescriptorsScan(TableDescriptor td, boolean forUpdate) throws StandardException {
    ConstraintDescriptorList cdl = td.getConstraintDescriptorList();
    DataValueDescriptor tableIDOrderable = null;
    TabInfoImpl ti = getNonCoreTI(SYSCONSTRAINTS_CATALOG_NUM);
    /* Use tableIDOrderable in both start and stop positions for scan */
    tableIDOrderable = getIDValueAsCHAR(td.getUUID());
    /* Set up the start/stop position for the scan */
    ExecIndexRow keyRow = (ExecIndexRow) exFactory.getIndexableRow(1);
    keyRow.setColumn(1, tableIDOrderable);
    getConstraintDescriptorViaIndex(SYSCONSTRAINTSRowFactory.SYSCONSTRAINTS_INDEX3_ID, keyRow, ti, td, cdl, forUpdate);
    cdl.setScanned(true);
}
Also used : ConstraintDescriptorList(org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList) DataValueDescriptor(org.apache.derby.iapi.types.DataValueDescriptor) ExecIndexRow(org.apache.derby.iapi.sql.execute.ExecIndexRow)

Example 4 with ConstraintDescriptorList

use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList in project derby by apache.

the class ModifyColumnNode method checkExistingConstraints.

/**
 * Check if the the column can be modified, and throw error if not.
 *
 * If the type of a column is being changed (for instance if the length
 * of the column is being increased) then make sure that this does not
 * violate any key constraints;
 * the column being altered is
 *   1. part of foreign key constraint
 *         ==&gt; ERROR. This references a Primary Key constraint and the
 *             type and lengths of the pkey/fkey must match exactly.
 *   2. part of a unique/primary key constraint
 *         ==&gt; OK if no fkey references this constraint.
 *         ==&gt; ERROR if any fkey in the system references this constraint.
 *
 * @param td		The Table Descriptor on which the ALTER is being done.
 *
 * @exception StandardException		Thrown on Error.
 */
void checkExistingConstraints(TableDescriptor td) throws StandardException {
    if ((kind != K_MODIFY_COLUMN_TYPE) && (kind != K_MODIFY_COLUMN_CONSTRAINT) && (kind != K_MODIFY_COLUMN_CONSTRAINT_NOT_NULL))
        return;
    DataDictionary dd = getDataDictionary();
    ConstraintDescriptorList cdl = dd.getConstraintDescriptors(td);
    int[] intArray = new int[1];
    intArray[0] = columnPosition;
    for (int index = 0; index < cdl.size(); index++) {
        ConstraintDescriptor existingConstraint = cdl.elementAt(index);
        if (!(existingConstraint instanceof KeyConstraintDescriptor))
            continue;
        if (!existingConstraint.columnIntersects(intArray))
            continue;
        int constraintType = existingConstraint.getConstraintType();
        // and fkey columns.
        if ((constraintType == DataDictionary.FOREIGNKEY_CONSTRAINT) && (kind == K_MODIFY_COLUMN_TYPE)) {
            throw StandardException.newException(SQLState.LANG_MODIFY_COLUMN_FKEY_CONSTRAINT, name, existingConstraint.getConstraintName());
        } else {
            if (!dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_4, null)) {
                // made nullable in soft upgrade mode from a pre-10.4 db.
                if (kind == K_MODIFY_COLUMN_CONSTRAINT && (existingConstraint.getConstraintType() == DataDictionary.UNIQUE_CONSTRAINT)) {
                    throw StandardException.newException(SQLState.LANG_MODIFY_COLUMN_EXISTING_CONSTRAINT, name);
                }
            }
            // is being made nullable; can't be done.
            if ((kind == K_MODIFY_COLUMN_CONSTRAINT) && ((existingConstraint.getConstraintType() == DataDictionary.PRIMARYKEY_CONSTRAINT))) {
                String errorState = (getLanguageConnectionContext().getDataDictionary().checkVersion(DataDictionary.DD_VERSION_DERBY_10_4, null)) ? SQLState.LANG_MODIFY_COLUMN_EXISTING_PRIMARY_KEY : SQLState.LANG_MODIFY_COLUMN_EXISTING_CONSTRAINT;
                throw StandardException.newException(errorState, name);
            }
            // unique key or primary key.
            ConstraintDescriptorList refcdl = dd.getForeignKeys(existingConstraint.getUUID());
            if (refcdl.size() > 0) {
                throw StandardException.newException(SQLState.LANG_MODIFY_COLUMN_REFERENCED, name, refcdl.elementAt(0).getConstraintName());
            }
            // Make the statement dependent on the primary key constraint.
            getCompilerContext().createDependency(existingConstraint);
        }
    }
}
Also used : ConstraintDescriptor(org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor) KeyConstraintDescriptor(org.apache.derby.iapi.sql.dictionary.KeyConstraintDescriptor) KeyConstraintDescriptor(org.apache.derby.iapi.sql.dictionary.KeyConstraintDescriptor) ConstraintDescriptorList(org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList) DataDictionary(org.apache.derby.iapi.sql.dictionary.DataDictionary)

Example 5 with ConstraintDescriptorList

use of org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList in project derby by apache.

the class RenameNode method renameColumnBind.

// do any checking needs to be done at bind time for rename column
private void renameColumnBind(DataDictionary dd) throws StandardException {
    ColumnDescriptor columnDescriptor = td.getColumnDescriptor(oldObjectName);
    /* Verify that old column name does exist in the table */
    if (columnDescriptor == null)
        throw StandardException.newException(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE, oldObjectName, getFullName());
    /* Verify that new column name does not exist in the table */
    ColumnDescriptor cd = td.getColumnDescriptor(newObjectName);
    if (cd != null)
        throw descriptorExistsException(cd, td);
    // 
    // You cannot rename a column which is referenced by the generation
    // clause of a generated column.
    // 
    ColumnDescriptorList generatedColumns = td.getGeneratedColumns();
    int generatedColumnCount = generatedColumns.size();
    for (int i = 0; i < generatedColumnCount; i++) {
        ColumnDescriptor gc = generatedColumns.elementAt(i);
        String[] referencedColumns = gc.getDefaultInfo().getReferencedColumnNames();
        int refColCount = referencedColumns.length;
        for (int j = 0; j < refColCount; j++) {
            String refName = referencedColumns[j];
            if (oldObjectName.equals(refName)) {
                throw StandardException.newException(SQLState.LANG_GEN_COL_BAD_RENAME, oldObjectName, gc.getColumnName());
            }
        }
    }
    /* Verify that there are no check constraints using the column being renamed */
    ConstraintDescriptorList constraintDescriptorList = dd.getConstraintDescriptors(td);
    int size = constraintDescriptorList == null ? 0 : constraintDescriptorList.size();
    ConstraintDescriptor constraintDescriptor;
    ColumnDescriptorList checkConstraintCDL;
    int checkConstraintCDLSize;
    // go through all the constraints defined on the table
    for (int index = 0; index < size; index++) {
        constraintDescriptor = constraintDescriptorList.elementAt(index);
        // renamed is not used in it's sql
        if (constraintDescriptor.getConstraintType() == DataDictionary.CHECK_CONSTRAINT) {
            checkConstraintCDL = constraintDescriptor.getColumnDescriptors();
            checkConstraintCDLSize = checkConstraintCDL.size();
            for (int index2 = 0; index2 < checkConstraintCDLSize; index2++) if (checkConstraintCDL.elementAt(index2) == columnDescriptor)
                throw StandardException.newException(SQLState.LANG_RENAME_COLUMN_WILL_BREAK_CHECK_CONSTRAINT, oldObjectName, constraintDescriptor.getConstraintName());
        }
    }
}
Also used : ColumnDescriptorList(org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList) ColumnDescriptor(org.apache.derby.iapi.sql.dictionary.ColumnDescriptor) ConstraintDescriptor(org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor) ConstraintDescriptorList(org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList)

Aggregations

ConstraintDescriptorList (org.apache.derby.iapi.sql.dictionary.ConstraintDescriptorList)24 ConstraintDescriptor (org.apache.derby.iapi.sql.dictionary.ConstraintDescriptor)15 ReferencedKeyConstraintDescriptor (org.apache.derby.iapi.sql.dictionary.ReferencedKeyConstraintDescriptor)10 DataDictionary (org.apache.derby.iapi.sql.dictionary.DataDictionary)7 ForeignKeyConstraintDescriptor (org.apache.derby.iapi.sql.dictionary.ForeignKeyConstraintDescriptor)7 ColumnDescriptor (org.apache.derby.iapi.sql.dictionary.ColumnDescriptor)6 LanguageConnectionContext (org.apache.derby.iapi.sql.conn.LanguageConnectionContext)5 ColumnDescriptorList (org.apache.derby.iapi.sql.dictionary.ColumnDescriptorList)5 TransactionController (org.apache.derby.iapi.store.access.TransactionController)5 ArrayList (java.util.ArrayList)4 FormatableBitSet (org.apache.derby.iapi.services.io.FormatableBitSet)4 DependencyManager (org.apache.derby.iapi.sql.depend.DependencyManager)4 ConglomerateDescriptor (org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)4 TableDescriptor (org.apache.derby.iapi.sql.dictionary.TableDescriptor)4 UUID (org.apache.derby.catalog.UUID)3 CheckConstraintDescriptor (org.apache.derby.iapi.sql.dictionary.CheckConstraintDescriptor)3 SchemaDescriptor (org.apache.derby.iapi.sql.dictionary.SchemaDescriptor)3 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)3 KeyConstraintDescriptor (org.apache.derby.iapi.sql.dictionary.KeyConstraintDescriptor)2 SubKeyConstraintDescriptor (org.apache.derby.iapi.sql.dictionary.SubKeyConstraintDescriptor)2