Search in sources :

Example 21 with MethodBuilder

use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.

the class ExpressionClassBuilder method beginConstructor.

// /////////////////////////////////////////////////////////////////////
// 
// CONSTRUCTOR MANAGEMENT
// 
// /////////////////////////////////////////////////////////////////////
private void beginConstructor() {
    // create a constructor that just calls super.
    MethodBuilder realConstructor = cb.newConstructorBuilder(Modifier.PUBLIC);
    realConstructor.callSuper();
    realConstructor.methodReturn();
    realConstructor.complete();
    constructor = cb.newMethodBuilder(Modifier.PUBLIC, "void", "postConstructor");
    constructor.addThrownException(ClassName.StandardException);
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 22 with MethodBuilder

use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.

the class StatementNode method generate.

/**
 * Do code generation for this statement.
 *
 * @param byteCode	the generated byte code for this statement.
 *			if non-null, then the byte code is saved
 *			here.
 *
 * @return		A GeneratedClass for this statement
 *
 * @exception StandardException		Thrown on error
 */
public GeneratedClass generate(ByteArray byteCode) throws StandardException {
    // start the new activation class.
    // it starts with the Execute method
    // and the appropriate superclass (based on
    // statement type, from inspecting the queryTree).
    int nodeChoice = activationKind();
    /* RESOLVE: Activation hierarchy was way too complicated
		 * and added no value.  Simple thing to do was to simply
		 * leave calling code alone and to handle here and to
		 * eliminate unnecessary classes.
		 */
    String superClass;
    switch(nodeChoice) {
        case NEED_CURSOR_ACTIVATION:
            superClass = ClassName.CursorActivation;
            break;
        case NEED_DDL_ACTIVATION:
            return getClassFactory().loadGeneratedClass("org.apache.derby.impl.sql.execute.ConstantActionActivation", null);
        case NEED_NOTHING_ACTIVATION:
        case NEED_ROW_ACTIVATION:
        case NEED_PARAM_ACTIVATION:
            superClass = ClassName.BaseActivation;
            break;
        default:
            throw StandardException.newException(SQLState.LANG_UNAVAILABLE_ACTIVATION_NEED, String.valueOf(nodeChoice));
    }
    ActivationClassBuilder generatingClass = new ActivationClassBuilder(superClass, getCompilerContext());
    // Create the method that generates the ResultSet tree used when
    // executing this statement. Implements the abstract method
    // BaseActivation.createResultSet().
    MethodBuilder mbWorker = generatingClass.getClassBuilder().newMethodBuilder(Modifier.PROTECTED, ClassName.ResultSet, "createResultSet");
    mbWorker.addThrownException(ClassName.StandardException);
    // Generate the complete ResultSet tree for this statement.
    // This step may add statements into the execute method
    // for per-execution actions.
    generate(generatingClass, mbWorker);
    mbWorker.methodReturn();
    mbWorker.complete();
    // wrap up the activation class definition
    // generate on the tree gave us back the newExpr
    // for getting a result set on the tree.
    // we put it in a return statement and stuff
    // it in the execute method of the activation.
    // The generated statement is the expression:
    // the activation class builder takes care of constructing it
    // for us, given the resultSetExpr to use.
    // return (this.resultSet = #resultSetExpr);
    generatingClass.finishExecuteMethod();
    // wrap up the constructor by putting a return at the end of it
    generatingClass.finishConstructor();
    try {
        // cook the completed class into a real class
        // and stuff it into activationClass
        GeneratedClass activationClass = generatingClass.getGeneratedClass(byteCode);
        return activationClass;
    } catch (StandardException e) {
        String msgId = e.getMessageId();
        if (SQLState.GENERATED_CLASS_LIMIT_EXCEEDED.equals(msgId) || SQLState.GENERATED_CLASS_LINKAGE_ERROR.equals(msgId)) {
            throw StandardException.newException(SQLState.LANG_QUERY_TOO_COMPLEX, e);
        }
        throw e;
    }
}
Also used : StandardException(org.apache.derby.shared.common.error.StandardException) GeneratedClass(org.apache.derby.iapi.services.loader.GeneratedClass) MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 23 with MethodBuilder

use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.

the class SubqueryNode method generateMaterialization.

/*
	** Materialize the subquery in question.  Given the expression
	** that represents the subquery, this returns fieldX where
	** fieldX is set up as follows:
	**
	** private ... fieldX
	**
	** execute()
	** {
	**	fieldX = <subqueryExpression>
	**	...
	** }
	**
	** So we wind up evaluating the subquery when we start
	** execution.  Obviously, it is absolutely necessary that
	** the subquery is invariant and has no correlations
	** for this to work.
	**
	** Ideally we wouldn't evaluate the expression subquery
	** until we know we need to, but because we are marking
	** this expression subquery as pushable, we must evaluate
	** it up front because it might wind up as a qualification,
	** and we cannot execute a subquery in the store as a
	** qualification because the store executes qualifications
	** while holding a latch.  
	**
	** @param acb
	** @param type 
	** @param subqueryExpression
	*/
private LocalField generateMaterialization(ActivationClassBuilder acb, MethodBuilder mbsq, String type) {
    MethodBuilder mb = acb.getExecuteMethod();
    // declare field
    LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, type);
    /* Generate the call to the new method */
    mb.pushThis();
    mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mbsq.getName(), type, 0);
    // generate: field = value (value is on stack)
    mb.setField(field);
    return field;
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder) LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 24 with MethodBuilder

use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.

the class PredicateList method generateIndexableRow.

/**
 * Generate the indexable row for a start key or stop key.
 *
 * @param acb	The ActivationClassBuilder for the class we're building
 * @param numberOfColumns	The number of columns in the key
 *
 * @return	The field that holds the indexable row
 */
private LocalField generateIndexableRow(ExpressionClassBuilder acb, int numberOfColumns) {
    MethodBuilder mb = acb.getConstructor();
    /*
		** Generate a call to get an indexable row
		** with the given number of columns
		*/
    // instance
    acb.pushGetExecutionFactoryExpression(mb);
    mb.push(numberOfColumns);
    mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ExecutionFactory, "getIndexableRow", ClassName.ExecIndexRow, 1);
    /*
		** Assign the indexable row to a field, and put this assignment into
		** the constructor for the activation class.  This way, we only have
		** to get the row once.
		*/
    LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.ExecIndexRow);
    mb.setField(field);
    return field;
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder) LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 25 with MethodBuilder

use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.

the class PredicateList method generateQualifiers.

/**
 * @see OptimizablePredicateList#generateQualifiers
 *
 * @exception StandardException		Thrown on error
 */
public void generateQualifiers(ExpressionClassBuilderInterface acbi, MethodBuilder mb, Optimizable optTable, boolean absolute) throws StandardException {
    String retvalType = ClassName.Qualifier + "[][]";
    // If there are no qualifiers, return null.
    if (numberOfQualifiers == 0) {
        mb.pushNull(retvalType);
        return;
    }
    ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi;
    MethodBuilder consMB = acb.getConstructor();
    MethodBuilder executeMB = acb.getExecuteMethod();
    /* Create and initialize the array of Qualifiers */
    LocalField qualField = acb.newFieldDeclaration(Modifier.PRIVATE, retvalType);
    /* 
		** Stick a reinitialize of the Qualifier array in execute().
		** Done because although we call Exec/Qualifier.clearOrderableCache() 
		** before each query, we only clear the cache for VARIANT and
		** SCAN_INVARIANT qualifiers.  However, each time the same
		** statement is executed, even the QUERY_INVARIANT qualifiers
		** need to be flushed.  For example:
		**	prepare select c1 from t where c1 = (select max(c1) from t) as p;
		**	execute p; -- we now have the materialized subquery result (1) 
		**			   -- in our predicate
		**	insert into t values 666;
		**	execute p; -- we need to clear out 1 and recache the subq result
		*/
    // PUSHCOMPILER
    // if (mb == executeMB) {
    // System.out.println("adding code to method in two places");
    // new Throwable().printStackTrace();
    // }
    // 
    // generate code to reinitializeQualifiers(Qualifier[][] qualifiers)
    // first arg to reinitializeQualifiers()
    executeMB.getField(qualField);
    executeMB.callMethod(VMOpcode.INVOKESTATIC, acb.getBaseClassName(), "reinitializeQualifiers", "void", 1);
    if (SanityManager.DEBUG) {
        if (numberOfQualifiers > size()) {
            SanityManager.THROWASSERT("numberOfQualifiers(" + numberOfQualifiers + ") > size(" + size() + ")." + ":" + this.hashCode());
        }
    }
    // Determine number of leading AND qualifiers, and subsequent
    // trailing OR qualifiers.
    int num_of_or_conjunctions = 0;
    for (int i = 0; i < numberOfQualifiers; i++) {
        if (elementAt(i).isOrList()) {
            num_of_or_conjunctions++;
        }
    }
    /* Assign the initializer to the Qualifier[] field */
    consMB.pushNewArray(ClassName.Qualifier + "[]", num_of_or_conjunctions + 1);
    consMB.setField(qualField);
    // Allocate qualifiers[0] which is an entry for each of the leading
    // AND clauses.
    // 1st arg allocateQualArray
    consMB.getField(qualField);
    // 2nd arg allocateQualArray
    consMB.push(0);
    // 3rd arg allocateQualArray
    consMB.push(numberOfQualifiers - num_of_or_conjunctions);
    consMB.callMethod(VMOpcode.INVOKESTATIC, acb.getBaseClassName(), "allocateQualArray", "void", 3);
    /* Sort the qualifiers by "selectivity" before generating.
		 * We want the qualifiers ordered by selectivity with the
		 * most selective ones first.  There are 3 groups of qualifiers:
		 * = and IS NULL are the most selective,
		 * <> and IS NOT NULL are the least selective and
		 * all of the other RELOPs are in between.
		 * We break the list into 4 parts (3 types of qualifiers and
		 * then everything else) and then rebuild the ordered list.
		 * RESOLVE - we will eventually want to order the qualifiers
		 * by (column #, selectivity) once the store does just in time
		 * instantiation.
		 */
    orderQualifiers();
    /* Generate each of the qualifiers, if any */
    // First generate the "leading" AND qualifiers.
    int qualNum = 0;
    int size = size();
    boolean gotOrQualifier = false;
    for (int index = 0; index < size; index++) {
        Predicate pred = elementAt(index);
        if (!pred.isQualifier()) {
            continue;
        } else if (pred.isOrList()) {
            gotOrQualifier = true;
            // will generate the OR qualifiers below.
            break;
        } else {
            generateSingleQualifierCode(consMB, optTable, absolute, acb, pred.getRelop(), qualField, 0, qualNum);
            qualNum++;
        }
    }
    if (gotOrQualifier) {
        // process each set of or's into a list which are AND'd.  Each
        // predicate will become an array list in the qualifier array of
        // array's.
        // 
        // The first list of And's went into qual[0][0...N]
        // Now each subquent predicate is actually a list of OR's so
        // will be passed as:
        // 1st OR predicate -> qual[1][0.. number of OR terms]
        // 2nd OR predicate -> qual[2][0.. number of OR terms]
        // ...
        // 
        int and_idx = 1;
        for (int index = qualNum; index < size; index++, and_idx++) {
            Predicate pred = elementAt(index);
            if (SanityManager.DEBUG) {
                SanityManager.ASSERT(pred.isOrList());
            }
            // create an ArrayList of the OR nodes.  We need the count
            // of Or's in order to first generate the allocateQualArray()
            // call, then we walk the list assigning each of the OR's to
            // entries in the array in generateSingleQualifierCode().
            ArrayList<RelationalOperator> a_list = new ArrayList<RelationalOperator>();
            QueryTreeNode node = pred.getAndNode().getLeftOperand();
            while (node instanceof OrNode) {
                OrNode or_node = (OrNode) node;
                // (ie. A = 1)
                if (or_node.getLeftOperand() instanceof RelationalOperator) {
                    a_list.add((RelationalOperator) or_node.getLeftOperand());
                }
                // The next OR node in the list if linked to the right.
                node = or_node.getRightOperand();
            }
            // Allocate an array to hold each of the terms of this OR,
            // clause.  ie. (a = 1 or b = 2), will allocate a 2 entry array.
            // 1st arg allocateQualArray
            consMB.getField(qualField);
            // 2nd arg allocateQualArray
            consMB.push(and_idx);
            // 3rd arg allocateQualArray
            consMB.push(a_list.size());
            consMB.callMethod(VMOpcode.INVOKESTATIC, acb.getBaseClassName(), "allocateQualArray", "void", 3);
            // finally transfer the nodes to the 2-d qualifier
            for (int i = 0; i < a_list.size(); i++) {
                generateSingleQualifierCode(consMB, optTable, absolute, acb, a_list.get(i), qualField, and_idx, i);
            }
            qualNum++;
        }
    }
    if (SanityManager.DEBUG) {
        SanityManager.ASSERT(qualNum == numberOfQualifiers, qualNum + " Qualifiers found, " + numberOfQualifiers + " expected.");
    }
    /*
		** Return a reference to the field that holds the initialized
		** array of Qualifiers.
		*/
    mb.getField(qualField);
}
Also used : ArrayList(java.util.ArrayList) MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder) LocalField(org.apache.derby.iapi.services.compiler.LocalField) OptimizablePredicate(org.apache.derby.iapi.sql.compile.OptimizablePredicate)

Aggregations

MethodBuilder (org.apache.derby.iapi.services.compiler.MethodBuilder)48 LocalField (org.apache.derby.iapi.services.compiler.LocalField)18 ReferencedColumnsDescriptorImpl (org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl)3 OptimizablePredicate (org.apache.derby.iapi.sql.compile.OptimizablePredicate)3 Method (java.lang.reflect.Method)1 ArrayList (java.util.ArrayList)1 FormatableArrayHolder (org.apache.derby.iapi.services.io.FormatableArrayHolder)1 FormatableIntHolder (org.apache.derby.iapi.services.io.FormatableIntHolder)1 GeneratedClass (org.apache.derby.iapi.services.loader.GeneratedClass)1 CompilerContext (org.apache.derby.iapi.sql.compile.CompilerContext)1 CostEstimate (org.apache.derby.iapi.sql.compile.CostEstimate)1 StaticCompiledOpenConglomInfo (org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo)1 DataTypeDescriptor (org.apache.derby.iapi.types.DataTypeDescriptor)1 SqlXmlUtil (org.apache.derby.iapi.types.SqlXmlUtil)1 StandardException (org.apache.derby.shared.common.error.StandardException)1