Search in sources :

Example 16 with LocalField

use of org.apache.derby.iapi.services.compiler.LocalField 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 17 with LocalField

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

the class UnaryOperatorNode method generateExpression.

/**
 * Do code generation for this unary operator.
 *
 * @param acb	The ExpressionClassBuilder for the class we're generating
 * @param mb	The method the expression will go into
 *
 * @exception StandardException		Thrown on error
 */
@Override
void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException {
    String resultTypeName = (kind == K_BASE) ? getTypeCompiler().interfaceName() : resultInterfaceType;
    // System.out.println("resultTypeName " + resultTypeName + " method " + methodName);
    // System.out.println("isBooleanTypeId() " + getTypeId().isBooleanTypeId());
    boolean needField = !getTypeId().isBooleanTypeId();
    String receiverType = getReceiverInterfaceName();
    operand.generateExpression(acb, mb);
    mb.cast(receiverType);
    if (needField) {
        /* Allocate an object for re-use to hold the result of the operator */
        LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName);
        mb.getField(field);
        int numArgs = 1;
        // XML operators take extra arguments.
        numArgs += addXmlOpMethodParams(acb, mb, field);
        mb.callMethod(VMOpcode.INVOKEINTERFACE, null, methodName, resultTypeName, numArgs);
        /*
			** Store the result of the method call in the field, so we can re-use
			** the object.
			*/
        mb.putField(field);
    } else {
        mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, methodName, resultTypeName, 0);
    }
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 18 with LocalField

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

the class TernaryOperatorNode method generateExpression.

/**
 * Do code generation for this ternary operator.
 *
 * @param acb	The ExpressionClassBuilder for the class we're generating
 * @param mb	The method the expression will go into
 *
 * @exception StandardException		Thrown on error
 */
@Override
void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException {
    int nargs = 0;
    String receiverType = null;
    /* Allocate an object for re-use to hold the result of the operator */
    LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultInterfaceType);
    receiver.generateExpression(acb, mb);
    if (kind == K_TRIM) {
        mb.push(trimType);
        leftOperand.generateExpression(acb, mb);
        mb.cast(leftInterfaceType);
        mb.getField(field);
        nargs = 3;
        receiverType = receiverInterfaceType;
    } else if (kind == K_LOCATE) {
        leftOperand.generateExpression(acb, mb);
        mb.upCast(leftInterfaceType);
        rightOperand.generateExpression(acb, mb);
        mb.upCast(rightInterfaceType);
        mb.getField(field);
        nargs = 3;
    } else if (kind == K_SUBSTRING) {
        leftOperand.generateExpression(acb, mb);
        mb.upCast(leftInterfaceType);
        if (rightOperand != null) {
            rightOperand.generateExpression(acb, mb);
            mb.upCast(rightInterfaceType);
        } else {
            mb.pushNull(rightInterfaceType);
        }
        // third arg
        mb.getField(field);
        mb.push(receiver.getTypeServices().getMaximumWidth());
        nargs = 4;
        receiverType = receiverInterfaceType;
    } else if (kind == K_TIMESTAMPADD || kind == K_TIMESTAMPDIFF) {
        Object intervalType = leftOperand.getConstantValueAsObject();
        if (SanityManager.DEBUG)
            SanityManager.ASSERT(intervalType != null && intervalType instanceof Integer, "Invalid interval type used for " + operator);
        mb.push(((Integer) intervalType).intValue());
        rightOperand.generateExpression(acb, mb);
        mb.upCast(TernaryArgType[kind][2]);
        acb.getCurrentDateExpression(mb);
        mb.getField(field);
        nargs = 4;
        receiverType = receiverInterfaceType;
    }
    mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultInterfaceType, nargs);
    /*
		** Store the result of the method call in the field, so we can re-use
		** the object.
		*/
    mb.putField(field);
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 19 with LocalField

use of org.apache.derby.iapi.services.compiler.LocalField 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 20 with LocalField

use of org.apache.derby.iapi.services.compiler.LocalField 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

LocalField (org.apache.derby.iapi.services.compiler.LocalField)32 MethodBuilder (org.apache.derby.iapi.services.compiler.MethodBuilder)18 OptimizablePredicate (org.apache.derby.iapi.sql.compile.OptimizablePredicate)3 TypeCompiler (org.apache.derby.iapi.sql.compile.TypeCompiler)2 Method (java.lang.reflect.Method)1 ArrayList (java.util.ArrayList)1 CompilerContext (org.apache.derby.iapi.sql.compile.CompilerContext)1 CostEstimate (org.apache.derby.iapi.sql.compile.CostEstimate)1 DataTypeDescriptor (org.apache.derby.iapi.types.DataTypeDescriptor)1 SqlXmlUtil (org.apache.derby.iapi.types.SqlXmlUtil)1 TypeId (org.apache.derby.iapi.types.TypeId)1