Search in sources :

Example 1 with CompilerContext

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

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

the class AggregateNode method bindExpression.

/**
 * Bind this operator.  Determine the type of the subexpression,
 * and pass that into the UserAggregate.
 *
 * @param fromList			The query's FROM list
 * @param subqueryList		The subquery list being built as we find SubqueryNodes
 * @param aggregates        The aggregate list being built as we find AggregateNodes
 *
 * @return	The new top of the expression tree.
 *
 * @exception StandardException		Thrown on error
 */
@Override
ValueNode bindExpression(FromList fromList, SubqueryList subqueryList, List<AggregateNode> aggregates) throws StandardException {
    DataDictionary dd = getDataDictionary();
    DataTypeDescriptor dts = null;
    ClassFactory cf;
    cf = getClassFactory();
    classInspector = cf.getClassInspector();
    boolean noSchema = true;
    if (userAggregateName != null) {
        noSchema = (userAggregateName.getSchemaName() == null);
        userAggregateName.bind();
    }
    // bind it now.
    if (userAggregateName != null && uad == null) {
        String schemaName = userAggregateName.getSchemaName();
        AliasDescriptor ad = resolveAggregate(dd, getSchemaDescriptor(schemaName, true), userAggregateName.getTableName(), noSchema);
        if (ad == null) {
            throw StandardException.newException(SQLState.LANG_OBJECT_NOT_FOUND, AliasDescriptor.getAliasType(AliasInfo.ALIAS_TYPE_AGGREGATE_AS_CHAR), userAggregateName.getTableName());
        }
        setUserDefinedAggregate(new UserAggregateDefinition(ad));
        aggregateName = ad.getJavaClassName();
    }
    instantiateAggDef();
    // if this is a user-defined aggregate
    if (isUserDefinedAggregate()) {
        AliasDescriptor ad = ((UserAggregateDefinition) uad).getAliasDescriptor();
        boolean isModernBuiltinAggregate = SchemaDescriptor.STD_SYSTEM_SCHEMA_NAME.equals(ad.getSchemaName());
        if (distinct && isModernBuiltinAggregate) {
            throw StandardException.newException(SQLState.LANG_BAD_DISTINCT_AGG);
        }
        // set up dependency on the user-defined aggregate and compile a check for USAGE
        // priv if needed
        getCompilerContext().createDependency(ad);
        if (isPrivilegeCollectionRequired()) {
            // 
            if (!isModernBuiltinAggregate) {
                getCompilerContext().addRequiredUsagePriv(ad);
            }
        }
    }
    // Add ourselves to the list of aggregates before we do anything else.
    aggregates.add(this);
    CompilerContext cc = getCompilerContext();
    // operand being null means a count(*)
    if (operand != null) {
        int previousReliability = orReliability(CompilerContext.AGGREGATE_RESTRICTION);
        bindOperand(fromList, subqueryList, aggregates);
        cc.setReliability(previousReliability);
        /*
			** Make sure that we don't have an aggregate 
			** IMMEDIATELY below us.  Don't search below
			** any ResultSetNodes.
			*/
        HasNodeVisitor visitor = new HasNodeVisitor(this.getClass(), ResultSetNode.class);
        operand.accept(visitor);
        if (visitor.hasNode()) {
            throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_CONTAINS_AGGREGATE, getSQLName());
        }
        // Also forbid any window function inside an aggregate unless in
        // subquery, cf. SQL 2003, section 10.9, SR 7 a).
        SelectNode.checkNoWindowFunctions(operand, aggregateName);
        /*
			** Check the type of the operand.  Make sure that the user
			** defined aggregate can handle the operand datatype.
			*/
        dts = operand.getTypeServices();
        /* Convert count(nonNullableColumn) to count(*)	*/
        if (uad instanceof CountAggregateDefinition && !dts.isNullable()) {
            setOperator(aggregateName);
            setMethodName(aggregateName);
        }
        /*
			** If we have a distinct, then the value expression
			** MUST implement Orderable because we are going
			** to process it using it as part of a sort.
			*/
        if (distinct) {
            /*
				** For now, we check to see if orderable() returns
				** true for this type.  In the future we may need
				** to check to see if the type implements Orderable
				**
				*/
            if (!operand.getTypeId().orderable(cf)) {
                throw StandardException.newException(SQLState.LANG_COLUMN_NOT_ORDERABLE_DURING_EXECUTION, dts.getTypeId().getSQLTypeName());
            }
        }
        /*
			** Don't allow an untyped null
			*/
        if (operand instanceof UntypedNullConstantNode) {
            throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_BAD_TYPE_NULL, getSQLName());
        }
    }
    /*
		** Ask the aggregate definition whether it can handle
	 	** the input datatype.
	 	*/
    aggregatorClassName = new StringBuffer();
    DataTypeDescriptor resultType = uad.getAggregator(dts, aggregatorClassName);
    if (resultType == null) {
        throw StandardException.newException(SQLState.LANG_USER_AGGREGATE_BAD_TYPE, getSQLName(), operand.getTypeId().getSQLTypeName());
    }
    // coerced to the expected input type of the aggregator.
    if (isUserDefinedAggregate()) {
        ValueNode castNode = ((UserAggregateDefinition) uad).castInputValue(operand, getContextManager());
        if (castNode != null) {
            operand = castNode.bindExpression(fromList, subqueryList, aggregates);
        }
    }
    checkAggregatorClassName(aggregatorClassName.toString());
    setType(resultType);
    return this;
}
Also used : ClassFactory(org.apache.derby.iapi.services.loader.ClassFactory) DataTypeDescriptor(org.apache.derby.iapi.types.DataTypeDescriptor) CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) DataDictionary(org.apache.derby.iapi.sql.dictionary.DataDictionary) AliasDescriptor(org.apache.derby.iapi.sql.dictionary.AliasDescriptor)

Example 3 with CompilerContext

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

the class AggregateNode method replaceAggregatesWithColumnReferences.

/**
 * Replace aggregates in the expression tree with a ColumnReference to
 * that aggregate, append the aggregate to the supplied RCL (assumed to
 * be from the child ResultSetNode) and return the ColumnReference.
 * This is useful for pushing aggregates in the Having clause down to
 * the user's select at parse time.  It is also used for moving around
 * Aggregates in the select list when creating the Group By node.  In
 * that case it is called <B> after </B> bind time, so we need to create
 * the column differently.
 *
 * @param rcl	The RCL to append to.
 * @param tableNumber	The tableNumber for the new ColumnReference
 *
 * @return ValueNode	The (potentially) modified tree.
 *
 * @exception StandardException			Thrown on error
 */
ValueNode replaceAggregatesWithColumnReferences(ResultColumnList rcl, int tableNumber) throws StandardException {
    /*
		** This call is idempotent.  Do
		** the right thing if we have already
		** replaced ourselves.
		*/
    if (generatedRef == null) {
        String generatedColName;
        CompilerContext cc = getCompilerContext();
        generatedColName = "SQLCol" + cc.getNextColumnNumber();
        generatedRC = new ResultColumn(generatedColName, this, getContextManager());
        generatedRC.markGenerated();
        /*
			** Parse time.	
			*/
        generatedRef = new ColumnReference(generatedRC.getName(), null, getContextManager());
        // RESOLVE - unknown nesting level, but not correlated, so nesting levels must be 0
        generatedRef.setSource(generatedRC);
        generatedRef.setNestingLevel(0);
        generatedRef.setSourceLevel(0);
        if (tableNumber != -1) {
            generatedRef.setTableNumber(tableNumber);
        }
        rcl.addResultColumn(generatedRC);
        /* 
			** Mark the ColumnReference as being generated to replace
			** an aggregate
			*/
        generatedRef.markGeneratedToReplaceAggregate();
    } else {
        rcl.addResultColumn(generatedRC);
    }
    return generatedRef;
}
Also used : CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext)

Example 4 with CompilerContext

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

the class QueryTreeNode method resolveTableToSynonym.

/**
 * Resolve table/view reference to a synonym. May have to follow a synonym chain.
 *
 * @param	tabName to match for a synonym
 *
 * @return	Synonym TableName if a match is found, NULL otherwise.
 *
 * @exception StandardException		Thrown on error
 */
TableName resolveTableToSynonym(TableName tabName) throws StandardException {
    DataDictionary dd = getDataDictionary();
    String nextSynonymTable = tabName.getTableName();
    String nextSynonymSchema = tabName.getSchemaName();
    boolean found = false;
    CompilerContext cc = getCompilerContext();
    // the following loop shouldn't loop forever.
    for (; ; ) {
        SchemaDescriptor nextSD = getSchemaDescriptor(nextSynonymSchema, false);
        if (nextSD == null || nextSD.getUUID() == null)
            break;
        AliasDescriptor nextAD = dd.getAliasDescriptor(nextSD.getUUID().toString(), nextSynonymTable, AliasInfo.ALIAS_NAME_SPACE_SYNONYM_AS_CHAR);
        if (nextAD == null)
            break;
        /* Query is dependent on the AliasDescriptor */
        cc.createDependency(nextAD);
        found = true;
        SynonymAliasInfo info = ((SynonymAliasInfo) nextAD.getAliasInfo());
        nextSynonymTable = info.getSynonymTable();
        nextSynonymSchema = info.getSynonymSchema();
    }
    if (!found)
        return null;
    TableName tableName = new TableName(nextSynonymSchema, nextSynonymTable, getContextManager());
    return tableName;
}
Also used : SchemaDescriptor(org.apache.derby.iapi.sql.dictionary.SchemaDescriptor) CompilerContext(org.apache.derby.iapi.sql.compile.CompilerContext) AliasDescriptor(org.apache.derby.iapi.sql.dictionary.AliasDescriptor) SynonymAliasInfo(org.apache.derby.catalog.types.SynonymAliasInfo) DataDictionary(org.apache.derby.iapi.sql.dictionary.DataDictionary)

Example 5 with CompilerContext

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

Aggregations

CompilerContext (org.apache.derby.iapi.sql.compile.CompilerContext)53 SchemaDescriptor (org.apache.derby.iapi.sql.dictionary.SchemaDescriptor)12 DataDictionary (org.apache.derby.iapi.sql.dictionary.DataDictionary)10 DataTypeDescriptor (org.apache.derby.iapi.types.DataTypeDescriptor)9 Parser (org.apache.derby.iapi.sql.compile.Parser)8 Visitable (org.apache.derby.iapi.sql.compile.Visitable)6 TypeId (org.apache.derby.iapi.types.TypeId)6 LanguageConnectionContext (org.apache.derby.iapi.sql.conn.LanguageConnectionContext)5 ProviderList (org.apache.derby.iapi.sql.depend.ProviderList)5 ConglomerateDescriptor (org.apache.derby.iapi.sql.dictionary.ConglomerateDescriptor)5 ArrayList (java.util.ArrayList)4 ColumnDescriptor (org.apache.derby.iapi.sql.dictionary.ColumnDescriptor)4 TableDescriptor (org.apache.derby.iapi.sql.dictionary.TableDescriptor)4 ContextManager (org.apache.derby.iapi.services.context.ContextManager)3 StandardException (org.apache.derby.shared.common.error.StandardException)3 UUID (org.apache.derby.catalog.UUID)2 DefaultInfoImpl (org.apache.derby.catalog.types.DefaultInfoImpl)2 ClassFactory (org.apache.derby.iapi.services.loader.ClassFactory)2 CostEstimate (org.apache.derby.iapi.sql.compile.CostEstimate)2 TypeCompilerFactory (org.apache.derby.iapi.sql.compile.TypeCompilerFactory)2