Search in sources :

Example 6 with SPSDescriptor

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

the class DataDictionaryImpl method getSPSDescriptorIndex2Scan.

/**
 * Scan sysstatements_index2 (stmtid) for a match.
 * Note that we do not do a lookup of parameter info.
 *
 * @return SPSDescriptor	The matching descriptor, if any.
 *
 * @exception StandardException		Thrown on failure
 */
private SPSDescriptor getSPSDescriptorIndex2Scan(String stmtUUID) throws StandardException {
    DataValueDescriptor stmtIDOrderable;
    TabInfoImpl ti = getNonCoreTI(SYSSTATEMENTS_CATALOG_NUM);
    /* Use stmtIdOrderable in both start 
		 * and stop position for scan. 
		 */
    stmtIDOrderable = new SQLChar(stmtUUID);
    /* Set up the start/stop position for the scan */
    ExecIndexRow keyRow = exFactory.getIndexableRow(1);
    keyRow.setColumn(1, stmtIDOrderable);
    SPSDescriptor spsd = getDescriptorViaIndex(SYSSTATEMENTSRowFactory.SYSSTATEMENTS_INDEX1_ID, keyRow, (ScanQualifier[][]) null, ti, (TupleDescriptor) null, (List<TupleDescriptor>) null, SPSDescriptor.class, false);
    return spsd;
}
Also used : TupleDescriptor(org.apache.derby.iapi.sql.dictionary.TupleDescriptor) SQLChar(org.apache.derby.iapi.types.SQLChar) DataValueDescriptor(org.apache.derby.iapi.types.DataValueDescriptor) ExecIndexRow(org.apache.derby.iapi.sql.execute.ExecIndexRow) SPSDescriptor(org.apache.derby.iapi.sql.dictionary.SPSDescriptor)

Example 7 with SPSDescriptor

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

the class CreateTriggerConstantAction method executeConstantAction.

/**
 * This is the guts of the Execution-time logic for CREATE TRIGGER.
 *
 * @see ConstantAction#executeConstantAction
 *
 * @exception StandardException		Thrown on failure
 */
public void executeConstantAction(Activation activation) throws StandardException {
    SPSDescriptor whenspsd = null;
    SPSDescriptor actionspsd;
    LanguageConnectionContext lcc = activation.getLanguageConnectionContext();
    DataDictionary dd = lcc.getDataDictionary();
    DependencyManager dm = dd.getDependencyManager();
    TransactionController tc = lcc.getTransactionExecute();
    /*
		** Indicate that we are about to modify the data dictionary.
		** 
		** We tell the data dictionary we're done writing at the end of
		** the transaction.
		*/
    dd.startWriting(lcc);
    SchemaDescriptor triggerSd = getSchemaDescriptorForCreate(dd, activation, triggerSchemaName);
    if (spsCompSchemaId == null) {
        SchemaDescriptor def = lcc.getDefaultSchema();
        if (def.getUUID() == null) {
            // Descriptor for default schema is stale,
            // look it up in the dictionary
            def = dd.getSchemaDescriptor(def.getDescriptorName(), tc, false);
        }
        /* 
			** It is possible for spsCompSchemaId to be null.  For instance, 
			** the current schema may not have been physically created yet but 
			** it exists "virtually".  In this case, its UUID will have the 
			** value of null meaning that it is not persistent.  e.g.:   
			**
			** CONNECT 'db;create=true' user 'ernie';
			** CREATE TABLE bert.t1 (i INT);
			** CREATE TRIGGER bert.tr1 AFTER INSERT ON bert.t1 
			**    FOR EACH STATEMENT MODE DB2SQL 
			**    SELECT * FROM SYS.SYSTABLES;
			**
			** Note that in the above case, the trigger action statement have a 
			** null compilation schema.  A compilation schema with null value 
			** indicates that the trigger action statement text does not have 
			** any dependencies with the CURRENT SCHEMA.  This means:
			**
			** o  It is safe to compile this statement in any schema since 
			**    there is no dependency with the CURRENT SCHEMA. i.e.: All 
			**    relevent identifiers are qualified with a specific schema.
			**
			** o  The statement cache mechanism can utilize this piece of 
			**    information to enable better statement plan sharing across 
			**    connections in different schemas; thus, avoiding unnecessary 
			**    statement compilation.
			*/
        if (def != null)
            spsCompSchemaId = def.getUUID();
    }
    String tabName;
    if (triggerTable != null) {
        triggerTableId = triggerTable.getUUID();
        tabName = triggerTable.getName();
    } else
        tabName = "with UUID " + triggerTableId;
    /* We need to get table descriptor again.  We simply can't trust the
		 * one we got at compile time, the lock on system table was released
		 * when compile was done, and the table might well have been dropped.
		 */
    triggerTable = dd.getTableDescriptor(triggerTableId);
    if (triggerTable == null) {
        throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tabName);
    }
    /* Lock the table for DDL.  Otherwise during our execution, the table
		 * might be changed, even dropped.  Beetle 4269
		 */
    lockTableForDDL(tc, triggerTable.getHeapConglomerateId(), true);
    /* get triggerTable again for correctness, in case it's changed before
		 * the lock is aquired
		 */
    triggerTable = dd.getTableDescriptor(triggerTableId);
    if (triggerTable == null) {
        throw StandardException.newException(SQLState.LANG_TABLE_NOT_FOUND_DURING_EXECUTION, tabName);
    }
    /*
		** Send an invalidate on the table from which
		** the triggering event emanates.  This it
		** to make sure that DML statements on this table
		** will be recompiled.  Do this before we create
		** our trigger spses lest we invalidate them just
		** after creating them.
		*/
    dm.invalidateFor(triggerTable, DependencyManager.CREATE_TRIGGER, lcc);
    /*
		** Lets get our trigger id up front, we'll use it when
	 	** we create our spses.
		*/
    UUID tmpTriggerId = dd.getUUIDFactory().createUUID();
    actionSPSId = (actionSPSId == null) ? dd.getUUIDFactory().createUUID() : actionSPSId;
    if (whenSPSId == null && whenText != null) {
        whenSPSId = dd.getUUIDFactory().createUUID();
    }
    DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
    /*
		** Create the trigger descriptor first so the trigger action
		** compilation can pick up the relevant trigger especially in 
		** the case of self triggering.
		*/
    TriggerDescriptor triggerd = ddg.newTriggerDescriptor(triggerSd, tmpTriggerId, triggerName, eventMask, isBefore, isRow, isEnabled, triggerTable, whenSPSId, actionSPSId, makeCreationTimestamp(dd), referencedCols, referencedColsInTriggerAction, originalActionText, referencingOld, referencingNew, oldReferencingName, newReferencingName, originalWhenText);
    dd.addDescriptor(triggerd, triggerSd, DataDictionary.SYSTRIGGERS_CATALOG_NUM, false, tc);
    /*	
		** If we have a WHEN action we create it now.
		*/
    if (whenText != null) {
        // The WHEN clause is just a search condition and not a full
        // SQL statement. Turn in into a VALUES statement.
        String whenValuesStmt = "VALUES " + whenText;
        whenspsd = createSPS(lcc, ddg, dd, tc, tmpTriggerId, triggerSd, whenSPSId, spsCompSchemaId, whenValuesStmt, true, triggerTable);
    }
    /*
		** Create the trigger action
		*/
    actionspsd = createSPS(lcc, ddg, dd, tc, tmpTriggerId, triggerSd, actionSPSId, spsCompSchemaId, actionText, false, triggerTable);
    /*
		** Make underlying spses dependent on the trigger.
		*/
    if (whenspsd != null) {
        dm.addDependency(triggerd, whenspsd, lcc.getContextManager());
    }
    dm.addDependency(triggerd, actionspsd, lcc.getContextManager());
    dm.addDependency(triggerd, triggerTable, lcc.getContextManager());
    // from the triggered statement or the WHEN clause.
    for (ProviderInfo info : providerInfo) {
        Provider provider = (Provider) info.getDependableFinder().getDependable(dd, info.getObjectId());
        dm.addDependency(triggerd, provider, lcc.getContextManager());
    }
    // store trigger's dependency on various privileges in the dependeny system
    storeViewTriggerDependenciesOnPrivileges(activation, triggerd);
}
Also used : DataDescriptorGenerator(org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator) SchemaDescriptor(org.apache.derby.iapi.sql.dictionary.SchemaDescriptor) ProviderInfo(org.apache.derby.iapi.sql.depend.ProviderInfo) LanguageConnectionContext(org.apache.derby.iapi.sql.conn.LanguageConnectionContext) DependencyManager(org.apache.derby.iapi.sql.depend.DependencyManager) DataDictionary(org.apache.derby.iapi.sql.dictionary.DataDictionary) TransactionController(org.apache.derby.iapi.store.access.TransactionController) UUID(org.apache.derby.catalog.UUID) SPSDescriptor(org.apache.derby.iapi.sql.dictionary.SPSDescriptor) TriggerDescriptor(org.apache.derby.iapi.sql.dictionary.TriggerDescriptor) Provider(org.apache.derby.iapi.sql.depend.Provider)

Example 8 with SPSDescriptor

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

the class AlterTableConstantAction method columnDroppedAndTriggerDependencies.

// For the trigger, get the trigger action sql provided by the user
// in the create trigger sql. This sql is saved in the system
// table. Since a column has been dropped from the trigger table,
// the trigger action sql may not be valid anymore. To establish
// that, we need to regenerate the internal representation of that
// sql and bind it again.
// 
// This method is called both on the WHEN clause (if one exists) and the
// triggered SQL statement of the trigger action.
// 
// Return true if the trigger was dropped by this method (if cascade is
// true and it turns out the trigger depends on the column being dropped),
// or false otherwise.
private boolean columnDroppedAndTriggerDependencies(TriggerDescriptor trd, UUID spsUUID, boolean isWhenClause, boolean cascade, String columnName) throws StandardException {
    dd.dropTriggerDescriptor(trd, tc);
    // Here we get the trigger action sql and use the parser to build
    // the parse tree for it.
    SchemaDescriptor compSchema = dd.getSchemaDescriptor(dd.getSPSDescriptor(spsUUID).getCompSchemaId(), null);
    CompilerContext newCC = lcc.pushCompilerContext(compSchema);
    Parser pa = newCC.getParser();
    String originalSQL = isWhenClause ? trd.getWhenClauseText() : trd.getTriggerDefinition();
    Visitable node = isWhenClause ? pa.parseSearchCondition(originalSQL) : pa.parseStatement(originalSQL);
    lcc.popCompilerContext(newCC);
    // Do not delete following. We use this in finally clause to
    // determine if the CompilerContext needs to be popped.
    newCC = null;
    try {
        // Regenerate the internal representation for the trigger action
        // sql using the ColumnReference classes in the parse tree. It
        // will catch dropped column getting used in trigger action sql
        // through the REFERENCING clause(this can happen only for the
        // the triggers created prior to 10.7. Trigger created with
        // 10.7 and higher keep track of trigger action column used
        // through the REFERENCING clause in system table and hence
        // use of dropped column will be detected earlier in this
        // method for such triggers).
        // 
        // We might catch errors like following during this step.
        // Say that following pre-10.7 trigger exists in the system and
        // user is dropping column c11. During the regeneration of the
        // internal trigger action sql format, we will catch that
        // column oldt.c11 does not exist anymore
        // CREATE TRIGGER DERBY4998_SOFT_UPGRADE_RESTRICT_tr1
        // AFTER UPDATE OF c12
        // ON DERBY4998_SOFT_UPGRADE_RESTRICT REFERENCING OLD AS oldt
        // FOR EACH ROW
        // SELECT oldt.c11 from DERBY4998_SOFT_UPGRADE_RESTRICT
        SPSDescriptor sps = isWhenClause ? trd.getWhenClauseSPS(lcc) : trd.getActionSPS(lcc);
        int[] referencedColsInTriggerAction = new int[td.getNumberOfColumns()];
        java.util.Arrays.fill(referencedColsInTriggerAction, -1);
        String newText = dd.getTriggerActionString(node, trd.getOldReferencingName(), trd.getNewReferencingName(), originalSQL, trd.getReferencedCols(), referencedColsInTriggerAction, 0, trd.getTableDescriptor(), trd.getTriggerEventMask(), true, null, null);
        if (isWhenClause) {
            // The WHEN clause is not a full SQL statement, just a search
            // condition, so we need to turn it into a statement in order
            // to create an SPS.
            newText = "VALUES " + newText;
        }
        sps.setText(newText);
        // Now that we have the internal format of the trigger action sql,
        // bind that sql to make sure that we are not using colunm being
        // dropped in the trigger action sql directly (ie not through
        // REFERENCING clause.
        // eg
        // create table atdc_12 (a integer, b integer);
        // create trigger atdc_12_trigger_1 after update of a
        // on atdc_12 for each row select a,b from atdc_12
        // Drop one of the columns used in the trigger action
        // alter table atdc_12 drop column b
        // Following rebinding of the trigger action sql will catch the use
        // of column b in trigger atdc_12_trigger_1
        newCC = lcc.pushCompilerContext(compSchema);
        newCC.setReliability(CompilerContext.INTERNAL_SQL_LEGAL);
        pa = newCC.getParser();
        StatementNode stmtnode = (StatementNode) pa.parseStatement(newText);
        // need a current dependent for bind
        newCC.setCurrentDependent(sps.getPreparedStatement());
        stmtnode.bindStatement();
    } catch (StandardException se) {
        // Ane drop column ATDC_13_TAB3.c12 is issued
        if (se.getMessageId().equals(SQLState.LANG_COLUMN_NOT_FOUND) || (se.getMessageId().equals(SQLState.LANG_COLUMN_NOT_FOUND_IN_TABLE) || (se.getMessageId().equals(SQLState.LANG_DB2_INVALID_COLS_SPECIFIED) || (se.getMessageId().equals(SQLState.LANG_TABLE_NOT_FOUND))))) {
            if (cascade) {
                trd.drop(lcc);
                activation.addWarning(StandardException.newWarning(SQLState.LANG_TRIGGER_DROPPED, trd.getName(), td.getName()));
                return true;
            } else {
                // we'd better give an error if don't drop it,
                throw StandardException.newException(SQLState.LANG_PROVIDER_HAS_DEPENDENT_OBJECT, dm.getActionString(DependencyManager.DROP_COLUMN), columnName, "TRIGGER", trd.getName());
            }
        } else
            throw se;
    } finally {
        if (newCC != null)
            lcc.popCompilerContext(newCC);
    }
    // If we are here, then it means that the column being dropped
    // is not getting used in the trigger action.
    // 
    // We have recreated the trigger action SPS and recollected the
    // column positions for trigger columns and trigger action columns
    // getting accessed through REFERENCING clause because
    // drop column can affect the column positioning of existing
    // columns in the table. We will save that in the system table.
    dd.addDescriptor(trd, sd, DataDictionary.SYSTRIGGERS_CATALOG_NUM, false, tc);
    return false;
}
Also used : StandardException(org.apache.derby.shared.common.error.StandardException) SchemaDescriptor(org.apache.derby.iapi.sql.dictionary.SchemaDescriptor) CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) Visitable(org.apache.derby.iapi.sql.compile.Visitable) StatementNode(org.apache.derby.impl.sql.compile.StatementNode) SPSDescriptor(org.apache.derby.iapi.sql.dictionary.SPSDescriptor) Parser(org.apache.derby.iapi.sql.compile.Parser)

Example 9 with SPSDescriptor

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

the class CreateTriggerConstantAction method createSPS.

/*
	** Create an sps that is used by the trigger.
	*/
private SPSDescriptor createSPS(LanguageConnectionContext lcc, DataDescriptorGenerator ddg, DataDictionary dd, TransactionController tc, UUID triggerId, SchemaDescriptor sd, UUID spsId, UUID compSchemaId, String text, boolean isWhen, TableDescriptor triggerTable) throws StandardException {
    if (text == null) {
        return null;
    }
    /*
		** Note: the format of this string is very important.
		** Dont change it arbitrarily -- see sps code.
		*/
    String spsName = "TRIGGER" + (isWhen ? "WHEN_" : "ACTN_") + triggerId + "_" + triggerTable.getUUID().toString();
    SPSDescriptor spsd = new SPSDescriptor(dd, spsName, (spsId == null) ? dd.getUUIDFactory().createUUID() : spsId, sd.getUUID(), compSchemaId == null ? lcc.getDefaultSchema().getUUID() : compSchemaId, SPSDescriptor.SPS_TYPE_TRIGGER, // it is valid
    true, // the text
    text, // no defaults
    true);
    /*
		** Prepared the stored prepared statement
		** and release the activation class -- we
		** know we aren't going to execute statement
		** after create it, so for now we are finished.
		*/
    spsd.prepareAndRelease(lcc, triggerTable);
    dd.addSPSDescriptor(spsd, tc);
    return spsd;
}
Also used : SPSDescriptor(org.apache.derby.iapi.sql.dictionary.SPSDescriptor)

Example 10 with SPSDescriptor

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

the class SYSSTATEMENTSRowFactory method buildDescriptor.

// /////////////////////////////////////////////////////////////////////////
// 
// ABSTRACT METHODS TO BE IMPLEMENTED BY CHILDREN OF CatalogRowFactory
// 
// /////////////////////////////////////////////////////////////////////////
/**
 * Make an  Tuple Descriptor out of a SYSSTATEMENTS row
 *
 * @param row 					a SYSSTATEMENTS row
 * @param parentTupleDescriptor	unused
 * @param dd 					dataDictionary
 *
 * @return	a  descriptor equivalent to a SYSSTATEMENTS row
 *
 * @exception   StandardException thrown on failure
 */
public TupleDescriptor buildDescriptor(ExecRow row, TupleDescriptor parentTupleDescriptor, DataDictionary dd) throws StandardException {
    DataValueDescriptor col;
    SPSDescriptor descriptor;
    String name;
    String text;
    String usingText;
    UUID uuid;
    UUID compUuid = null;
    String uuidStr;
    // schema
    UUID suuid;
    // schema
    String suuidStr;
    String typeStr;
    char type;
    boolean valid;
    Timestamp time = null;
    ExecPreparedStatement preparedStatement = null;
    boolean initiallyCompilable;
    DataDescriptorGenerator ddg = dd.getDataDescriptorGenerator();
    if (SanityManager.DEBUG) {
        SanityManager.ASSERT(row.nColumns() == SYSSTATEMENTS_COLUMN_COUNT, "Wrong number of columns for a SYSSTATEMENTS row");
    }
    // 1st column is STMTID (UUID - char(36))
    col = row.getColumn(1);
    uuidStr = col.getString();
    uuid = getUUIDFactory().recreateUUID(uuidStr);
    // 2nd column is STMTNAME (varchar(128))
    col = row.getColumn(2);
    name = col.getString();
    // 3rd column is SCHEMAID (UUID - char(36))
    col = row.getColumn(3);
    suuidStr = col.getString();
    suuid = getUUIDFactory().recreateUUID(suuidStr);
    // 4th column is TYPE (char(1))
    col = row.getColumn(4);
    type = col.getString().charAt(0);
    if (SanityManager.DEBUG) {
        if (!SPSDescriptor.validType(type)) {
            SanityManager.THROWASSERT("Bad type value (" + type + ") for  statement " + name);
        }
    }
    // so force a recompile.
    if (dd.isReadOnlyUpgrade()) {
        valid = false;
    } else {
        // 5th column is VALID (boolean)
        col = row.getColumn(5);
        valid = col.getBoolean();
    }
    // 6th column is TEXT (LONG VARCHAR)
    col = row.getColumn(6);
    text = col.getString();
    /* 7th column is LASTCOMPILED (TIMESTAMP) */
    col = row.getColumn(7);
    time = col.getTimestamp(new java.util.GregorianCalendar());
    // 8th column is COMPILATIONSCHEMAID (UUID - char(36))
    col = row.getColumn(8);
    uuidStr = col.getString();
    if (uuidStr != null)
        compUuid = getUUIDFactory().recreateUUID(uuidStr);
    // 9th column is TEXT (LONG VARCHAR)
    col = row.getColumn(9);
    usingText = col.getString();
    // Only load the compiled plan if the statement is valid
    if (valid) {
        col = row.getColumn(10);
        preparedStatement = (ExecPreparedStatement) col.getObject();
    }
    // 11th column is INITIALLY_COMPILABLE (boolean)
    col = row.getColumn(11);
    if (col.isNull()) {
        initiallyCompilable = true;
    } else {
        initiallyCompilable = col.getBoolean();
    }
    descriptor = new SPSDescriptor(dd, name, uuid, suuid, compUuid, type, valid, text, usingText, time, preparedStatement, initiallyCompilable);
    return descriptor;
}
Also used : DataDescriptorGenerator(org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator) ExecPreparedStatement(org.apache.derby.iapi.sql.execute.ExecPreparedStatement) SQLVarchar(org.apache.derby.iapi.types.SQLVarchar) DataValueDescriptor(org.apache.derby.iapi.types.DataValueDescriptor) UUID(org.apache.derby.catalog.UUID) Timestamp(java.sql.Timestamp) SPSDescriptor(org.apache.derby.iapi.sql.dictionary.SPSDescriptor)

Aggregations

SPSDescriptor (org.apache.derby.iapi.sql.dictionary.SPSDescriptor)14 UUID (org.apache.derby.catalog.UUID)4 SchemaDescriptor (org.apache.derby.iapi.sql.dictionary.SchemaDescriptor)4 DataDescriptorGenerator (org.apache.derby.iapi.sql.dictionary.DataDescriptorGenerator)3 DataDictionary (org.apache.derby.iapi.sql.dictionary.DataDictionary)3 DataValueDescriptor (org.apache.derby.iapi.types.DataValueDescriptor)3 LanguageConnectionContext (org.apache.derby.iapi.sql.conn.LanguageConnectionContext)2 DependencyManager (org.apache.derby.iapi.sql.depend.DependencyManager)2 TupleDescriptor (org.apache.derby.iapi.sql.dictionary.TupleDescriptor)2 ExecIndexRow (org.apache.derby.iapi.sql.execute.ExecIndexRow)2 SQLChar (org.apache.derby.iapi.types.SQLChar)2 SQLVarchar (org.apache.derby.iapi.types.SQLVarchar)2 StandardException (org.apache.derby.shared.common.error.StandardException)2 Timestamp (java.sql.Timestamp)1 ArrayList (java.util.ArrayList)1 Enumeration (java.util.Enumeration)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Properties (java.util.Properties)1 CacheFactory (org.apache.derby.iapi.services.cache.CacheFactory)1