Search in sources :

Example 1 with Parser

use of org.apache.derby.iapi.sql.compile.Parser in project derby by apache.

the class TriggerDescriptor method getSPS.

/**
 * Get the SPS for the triggered SQL statement or the WHEN clause.
 *
 * @param lcc the LanguageConnectionContext to use
 * @param isWhenClause {@code true} if the SPS for the WHEN clause is
 *   requested, {@code false} if it is the triggered SQL statement
 * @return the requested SPS
 * @throws StandardException if an error occurs
 */
private SPSDescriptor getSPS(LanguageConnectionContext lcc, boolean isWhenClause) throws StandardException {
    DataDictionary dd = getDataDictionary();
    SPSDescriptor sps = isWhenClause ? whenSPS : actionSPS;
    UUID spsId = isWhenClause ? whenSPSId : actionSPSId;
    String originalSQL = isWhenClause ? whenClauseText : triggerDefinition;
    if (sps == null) {
        // bug 4821 - do the sysstatement look up in a nested readonly
        // transaction rather than in the user transaction. Because of
        // this, the nested compile transaction which is attempting to
        // compile the trigger will not run into any locking issues with
        // the user transaction for sysstatements.
        lcc.beginNestedTransaction(true);
        sps = dd.getSPSDescriptor(spsId);
        lcc.commitNestedTransaction();
    }
    // We need to regenerate the trigger action sql if
    // 1)the trigger is found to be invalid,
    // 2)the trigger is defined at row level (that is the only kind of
    // trigger which allows reference to individual columns from
    // old/new row)
    // 3)the trigger action plan has columns that reference
    // old/new row columns(if we are working with pre-10.9 db,
    // meaning we are in soft-upgrade mode, then we won't have
    // information about the actual trigger action columns since
    // we didn't keep that info in those releases. For such dbs,
    // we will just check if they are using REFERENCING OLD and/or
    // NEW clause.)
    // This code was added as part of DERBY-4874 where the Alter table
    // had changed the length of a varchar column from varchar(30) to
    // varchar(64) but the trigger action plan continued to use varchar(30).
    // To fix varchar(30) in trigger action sql to varchar(64), we need
    // to regenerate the trigger action sql. This new trigger action sql
    // will then get updated into SYSSTATEMENTS table.
    boolean in10_9_orHigherVersion = dd.checkVersion(DataDictionary.DD_VERSION_DERBY_10_9, null);
    boolean usesReferencingClause = (in10_9_orHigherVersion) ? referencedColsInTriggerAction != null : (referencingOld || referencingNew);
    if ((!sps.isValid() || (sps.getPreparedStatement() == null)) && isRow && usesReferencingClause) {
        CompilerContext newCC = lcc.pushCompilerContext(dd.getSchemaDescriptor(sps.getCompSchemaId(), null));
        Parser pa = newCC.getParser();
        Visitable stmtnode = isWhenClause ? pa.parseSearchCondition(originalSQL) : pa.parseStatement(originalSQL);
        lcc.popCompilerContext(newCC);
        int[] cols;
        cols = dd.examineTriggerNodeAndCols(stmtnode, oldReferencingName, newReferencingName, originalSQL, referencedCols, referencedColsInTriggerAction, 0, getTableDescriptor(), -1, false, null);
        String newText = dd.getTriggerActionString(stmtnode, oldReferencingName, newReferencingName, originalSQL, referencedCols, referencedColsInTriggerAction, 0, getTableDescriptor(), -1, false, null, cols);
        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);
    // By this point, we are finished transforming the trigger action if
    // it has any references to old/new transition variables.
    }
    return sps;
}
Also used : CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) Visitable(org.apache.derby.iapi.sql.compile.Visitable) UUID(org.apache.derby.catalog.UUID) Parser(org.apache.derby.iapi.sql.compile.Parser)

Example 2 with Parser

use of org.apache.derby.iapi.sql.compile.Parser in project derby by apache.

the class QueryTreeNode method parseStatementOrSearchCondition.

/**
 * Parse a full SQL statement or a fragment representing a {@code <search
 * condition>}. This is a worker method that contains common logic for
 * {@link #parseStatement} and {@link #parseSearchCondition}.
 *
 * @param sql the SQL statement or fragment to parse
 * @param internalSQL {@code true} if it is allowed to contain internal
 *   syntax, {@code false} otherwise
 * @param isStatement {@code true} if {@code sql} is a full SQL statement,
 *   {@code false} if it is a fragment
 * @return a parse tree
 * @throws StandardException if an error happens while parsing
 */
private Visitable parseStatementOrSearchCondition(String sql, boolean internalSQL, boolean isStatement) throws StandardException {
    /*
		** Get a new compiler context, so the parsing of the text
		** doesn't mess up anything in the current context 
		*/
    LanguageConnectionContext lcc = getLanguageConnectionContext();
    CompilerContext newCC = lcc.pushCompilerContext();
    if (internalSQL)
        newCC.setReliability(CompilerContext.INTERNAL_SQL_LEGAL);
    try {
        Parser p = newCC.getParser();
        return isStatement ? p.parseStatement(sql) : p.parseSearchCondition(sql);
    } finally {
        lcc.popCompilerContext(newCC);
    }
}
Also used : LanguageConnectionContext(org.apache.derby.iapi.sql.conn.LanguageConnectionContext) CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) Parser(org.apache.derby.iapi.sql.compile.Parser)

Example 3 with Parser

use of org.apache.derby.iapi.sql.compile.Parser in project derby by apache.

the class ResultSetNode method parseDefault.

/**
 *	Parse a default and turn it into a query tree.
 *
 *	@param	defaultText			Text of Default.
 *
 * @return	The parsed default as a query tree.
 *
 * @exception StandardException		Thrown on failure
 */
public ValueNode parseDefault(String defaultText) throws StandardException {
    Parser p;
    ValueNode defaultTree;
    LanguageConnectionContext lcc = getLanguageConnectionContext();
    /* Get a Statement to pass to the parser */
    /* We're all set up to parse. We have to build a compilable SQL statement
		 * before we can parse -  So, we goober up a VALUES defaultText.
		 */
    String values = "VALUES " + defaultText;
    /*
		** Get a new compiler context, so the parsing of the select statement
		** doesn't mess up anything in the current context (it could clobber
		** the ParameterValueSet, for example).
		*/
    CompilerContext newCC = lcc.pushCompilerContext();
    p = newCC.getParser();
    /* Finally, we can call the parser */
    // Since this is always nested inside another SQL statement, so topLevel flag
    // should be false
    Visitable qt = p.parseStatement(values);
    if (SanityManager.DEBUG) {
        if (!(qt instanceof CursorNode)) {
            SanityManager.THROWASSERT("qt expected to be instanceof CursorNode, not " + qt.getClass().getName());
        }
        CursorNode cn = (CursorNode) qt;
        if (!(cn.getResultSetNode() instanceof RowResultSetNode)) {
            SanityManager.THROWASSERT("cn.getResultSetNode() expected to be instanceof RowResultSetNode, not " + cn.getResultSetNode().getClass().getName());
        }
    }
    defaultTree = ((CursorNode) qt).getResultSetNode().getResultColumns().elementAt(0).getExpression();
    lcc.popCompilerContext(newCC);
    return defaultTree;
}
Also used : LanguageConnectionContext(org.apache.derby.iapi.sql.conn.LanguageConnectionContext) CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) Visitable(org.apache.derby.iapi.sql.compile.Visitable) Parser(org.apache.derby.iapi.sql.compile.Parser)

Example 4 with Parser

use of org.apache.derby.iapi.sql.compile.Parser in project derby by apache.

the class DMLModStatementNode method parseCheckConstraint.

/**
 *	Parse a check constraint and turn it into a query tree.
 *
 *	@param	checkConstraintText	Text of CHECK CONSTRAINT.
 * @param	td					The TableDescriptor for the table the the constraint is on.
 *
 * @return	The parsed check constraint as a query tree.
 *
 * @exception StandardException		Thrown on failure
 */
public ValueNode parseCheckConstraint(String checkConstraintText, TableDescriptor td) throws StandardException {
    Parser p;
    ValueNode checkTree;
    LanguageConnectionContext lcc = getLanguageConnectionContext();
    /* Get a Statement to pass to the parser */
    /* We're all set up to parse. We have to build a compile SQL statement
		 * before we can parse - we just have a WHERE clause right now.
		 * So, we goober up a SELECT * FROM table WHERE checkDefs.
		 */
    String select = "SELECT * FROM " + td.getQualifiedName() + " WHERE " + checkConstraintText;
    /*
		** Get a new compiler context, so the parsing of the select statement
		** doesn't mess up anything in the current context (it could clobber
		** the ParameterValueSet, for example).
		*/
    CompilerContext newCC = lcc.pushCompilerContext();
    p = newCC.getParser();
    /* Finally, we can call the parser */
    // Since this is always nested inside another SQL statement, so topLevel flag
    // should be false
    Visitable qt = p.parseStatement(select);
    if (SanityManager.DEBUG) {
        if (!(qt instanceof CursorNode)) {
            SanityManager.THROWASSERT("qt expected to be instanceof CursorNode, not " + qt.getClass().getName());
        }
        CursorNode cn = (CursorNode) qt;
        if (!(cn.getResultSetNode() instanceof SelectNode)) {
            SanityManager.THROWASSERT("cn.getResultSetNode() expected to be instanceof SelectNode, not " + cn.getResultSetNode().getClass().getName());
        }
    }
    checkTree = ((SelectNode) ((CursorNode) qt).getResultSetNode()).getWhereClause();
    lcc.popCompilerContext(newCC);
    return checkTree;
}
Also used : LanguageConnectionContext(org.apache.derby.iapi.sql.conn.LanguageConnectionContext) CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) Visitable(org.apache.derby.iapi.sql.compile.Visitable) Parser(org.apache.derby.iapi.sql.compile.Parser)

Example 5 with Parser

use of org.apache.derby.iapi.sql.compile.Parser 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)

Aggregations

CompilerContext (org.apache.derby.iapi.sql.compile.CompilerContext)8 Parser (org.apache.derby.iapi.sql.compile.Parser)8 Visitable (org.apache.derby.iapi.sql.compile.Visitable)6 LanguageConnectionContext (org.apache.derby.iapi.sql.conn.LanguageConnectionContext)4 StatementNode (org.apache.derby.impl.sql.compile.StatementNode)2 StandardException (org.apache.derby.shared.common.error.StandardException)2 Timestamp (java.sql.Timestamp)1 UUID (org.apache.derby.catalog.UUID)1 IndexStatisticsDaemon (org.apache.derby.iapi.services.daemon.IndexStatisticsDaemon)1 GeneratedClass (org.apache.derby.iapi.services.loader.GeneratedClass)1 StatementContext (org.apache.derby.iapi.sql.conn.StatementContext)1 DataDictionary (org.apache.derby.iapi.sql.dictionary.DataDictionary)1 SPSDescriptor (org.apache.derby.iapi.sql.dictionary.SPSDescriptor)1 SchemaDescriptor (org.apache.derby.iapi.sql.dictionary.SchemaDescriptor)1 TableDescriptor (org.apache.derby.iapi.sql.dictionary.TableDescriptor)1 GenericLanguageConnectionContext (org.apache.derby.impl.sql.conn.GenericLanguageConnectionContext)1 HeaderPrintWriter (org.apache.derby.shared.common.stream.HeaderPrintWriter)1