Search in sources :

Example 1 with MethodBuilder

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

the class ActivationClassBuilder method getCurrentSetup.

// /////////////////////////////////////////////////////////////////////
// 
// CURRENT DATE/TIME SUPPORT
// 
// /////////////////////////////////////////////////////////////////////
/*
		The first time a current datetime is needed, create the class
		level support for it. The first half of the logic is in our parent
		class.
	 */
@Override
protected LocalField getCurrentSetup() {
    if (cdtField != null)
        return cdtField;
    LocalField lf = super.getCurrentSetup();
    // 3) the execute method gets a statement (prior to the return)
    // to tell cdt to restart:
    // cdt.forget();
    MethodBuilder execute = getExecuteMethod();
    execute.getField(lf);
    execute.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, "forget", "void", 0);
    return lf;
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField) MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 2 with MethodBuilder

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

the class PredicateList method generateStartKey.

/**
 * @see OptimizablePredicateList#generateStartKey
 *
 * @exception StandardException		Thrown on error
 */
public void generateStartKey(ExpressionClassBuilderInterface acbi, MethodBuilder mb, Optimizable optTable) throws StandardException {
    ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi;
    if (numberOfStartPredicates != 0) {
        /* This sets up the method and the static field */
        MethodBuilder exprFun = acb.newExprFun();
        /* Now we fill in the body of the method */
        LocalField rowField = generateIndexableRow(acb, numberOfStartPredicates);
        int colNum = 0;
        for (Predicate pred : this) {
            if (!pred.isStartKey())
                continue;
            generateSetColumn(acb, exprFun, colNum, pred, optTable, rowField, true);
            colNum++;
        }
        if (SanityManager.DEBUG) {
            SanityManager.ASSERT(colNum == numberOfStartPredicates, "Number of start predicates does not match");
        }
        finishKey(acb, mb, exprFun, rowField);
        return;
    }
    mb.pushNull(ClassName.GeneratedMethod);
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder) LocalField(org.apache.derby.iapi.services.compiler.LocalField) OptimizablePredicate(org.apache.derby.iapi.sql.compile.OptimizablePredicate)

Example 3 with MethodBuilder

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

the class PredicateList method generateSetColumn.

/**
 * Generate the code to set the value from a predicate in an index column.
 *
 * @param acb	The ActivationClassBuilder for the class we're building
 * @param exprFun	The MethodBuilder for the method we're building
 * @param columnNumber	The position number of the column we're setting
 *						the value in (zero-based)
 * @param pred	The Predicate with the value to put in the index column
 * @param optTable	The Optimizable table the column is in
 * @param rowField	The field that holds the indexable row
 * @param isStartKey Are we generating start or stop key?  This information
 *					 is useful for "in"'s dynamic start/stop key, bug 3858
 *
 * @exception StandardException		Thrown on error
 */
private void generateSetColumn(ExpressionClassBuilder acb, MethodBuilder exprFun, int columnNumber, Predicate pred, Optimizable optTable, LocalField rowField, boolean isStartKey) throws StandardException {
    MethodBuilder mb;
    /* Code gets generated in constructor if comparison against
		 * a constant, otherwise gets generated in the current
		 * statement block.
		 */
    boolean withKnownConstant = false;
    if (pred.compareWithKnownConstant(optTable, false)) {
        withKnownConstant = true;
        mb = acb.getConstructor();
    } else {
        mb = exprFun;
    }
    int[] baseColumns = optTable.getTrulyTheBestAccessPath().getConglomerateDescriptor().getIndexDescriptor().baseColumnPositions();
    boolean[] isAscending = optTable.getTrulyTheBestAccessPath().getConglomerateDescriptor().getIndexDescriptor().isAscending();
    /* If the predicate is an IN-list probe predicate then we are
		 * using it as a start/stop key "placeholder", to be over-ridden
		 * at execution time.  Put differently, we want to generate
		 * "column = ?" as a start/stop key and then use the "?" value
		 * as a placeholder into which we'll plug the various IN values
		 * at execution time.
		 *
		 * In that case "isIn" will be false here, which is fine: there's
		 * no need to generate dynamic start/stop keys like we do for
		 * "normal" IN lists because we're just using the key as a place-
		 * holder.  So by generating the probe predicate ("column = ?")
		 * as a normal one-sided start/stop key, we get our requisite
		 * execution-time placeholder and that's that.  For more on how
		 * we use this "placeholder", see MultiProbeTableScanResultSet.
		 *
		 * Note that we generate the corresponding IN-list values
		 * separately (see generateInListValues() in this class).
		 */
    boolean isIn = pred.getAndNode().getLeftOperand() instanceof InListOperatorNode;
    /*
		** Generate statements of the form
		**
		** r.setColumn(columnNumber, columnExpression);
		**
		** and put the generated statement in the allocator function.
		*/
    mb.getField(rowField);
    mb.push(columnNumber + 1);
    // second arg
    if (isIn) {
        pred.getSourceInList().generateStartStopKey(isAscending[columnNumber], isStartKey, acb, mb);
    } else
        pred.generateExpressionOperand(optTable, baseColumns[columnNumber], acb, mb);
    mb.upCast(ClassName.DataValueDescriptor);
    mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2);
    /* Also tell the row if this column uses ordered null semantics */
    if (!isIn) {
        RelationalOperator relop = pred.getRelop();
        boolean setOrderedNulls = relop.orderedNulls();
        /* beetle 4464, performance work.  If index column is not nullable 
             * (which is frequent), we should treat it as though nulls are 
             * ordered (indeed because they don't exist) so that we do not have
             * to check null at scan time for each row, each column.  This is 
             * an overload to "is null" operator, so that we have less overhead,
             * provided that they don't interfere.  It doesn't interfere if it 
             * doesn't overload if key is null.  If key is null, but operator
			 * is not orderedNull type (is null), skipScan will use this flag 
             * (false) to skip scan.
			 */
        if ((!setOrderedNulls) && !relop.getColumnOperand(optTable).getTypeServices().isNullable()) {
            if (withKnownConstant)
                setOrderedNulls = true;
            else {
                ValueNode keyExp = relop.getExpressionOperand(optTable.getTableNumber(), baseColumns[columnNumber], (FromTable) optTable);
                if (keyExp instanceof ColumnReference)
                    setOrderedNulls = !((ColumnReference) keyExp).getTypeServices().isNullable();
            }
        }
        if (setOrderedNulls) {
            mb.getField(rowField);
            mb.push(columnNumber);
            mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ExecIndexRow, "orderedNulls", "void", 1);
        }
    }
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 4 with MethodBuilder

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

the class PredicateList method generateStopKey.

/**
 * @see OptimizablePredicateList#generateStopKey
 *
 * @exception StandardException		Thrown on error
 */
public void generateStopKey(ExpressionClassBuilderInterface acbi, MethodBuilder mb, Optimizable optTable) throws StandardException {
    ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi;
    if (numberOfStopPredicates != 0) {
        /* This sets up the method and the static field */
        MethodBuilder exprFun = acb.newExprFun();
        /* Now we fill in the body of the method */
        LocalField rowField = generateIndexableRow(acb, numberOfStopPredicates);
        int colNum = 0;
        for (Predicate pred : this) {
            if (!pred.isStopKey())
                continue;
            generateSetColumn(acb, exprFun, colNum, pred, optTable, rowField, false);
            colNum++;
        }
        if (SanityManager.DEBUG) {
            SanityManager.ASSERT(colNum == numberOfStopPredicates, "Number of stop predicates does not match");
        }
        finishKey(acb, mb, exprFun, rowField);
        return;
    }
    mb.pushNull(ClassName.GeneratedMethod);
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder) LocalField(org.apache.derby.iapi.services.compiler.LocalField) OptimizablePredicate(org.apache.derby.iapi.sql.compile.OptimizablePredicate)

Example 5 with MethodBuilder

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

the class HashTableNode method generateMinion.

/**
 * Logic shared by generate() and generateResultSet().
 *
 * @param acb	The ExpressionClassBuilder for the class being built
 * @param mb the method  the expression will go into
 *
 * @exception StandardException		Thrown on error
 */
private void generateMinion(ExpressionClassBuilder acb, MethodBuilder mb, boolean genChildResultSet) throws StandardException {
    MethodBuilder userExprFun;
    ValueNode searchClause = null;
    ValueNode equijoinClause = null;
    /* The tableProperties, if non-null, must be correct to get this far.
		 * We simply call verifyProperties to set initialCapacity and
		 * loadFactor.
		 */
    verifyProperties(getDataDictionary());
    /* Put the predicates back into the tree */
    if (searchPredicateList != null) {
        // Remove any redundant predicates before restoring
        searchPredicateList.removeRedundantPredicates();
        searchClause = searchPredicateList.restorePredicates();
        /* Allow the searchPredicateList to get garbage collected now
			 * that we're done with it.
			 */
        searchPredicateList = null;
    }
    // for the single table predicates, we generate an exprFun
    // that evaluates the expression of the clause
    // against the current row of the child's result.
    // if the restriction is empty, simply pass null
    // to optimize for run time performance.
    // generate the function and initializer:
    // Note: Boolean lets us return nulls (boolean would not)
    // private Boolean exprN()
    // {
    // return <<searchClause.generate(ps)>>;
    // }
    // static Method exprN = method pointer to exprN;
    // Map the result columns to the source columns
    ResultColumnList.ColumnMapping mappingArrays = getResultColumns().mapSourceColumns();
    int[] mapArray = mappingArrays.mapArray;
    int mapArrayItem = acb.addItem(new ReferencedColumnsDescriptorImpl(mapArray));
    // Save the hash key columns
    FormatableIntHolder[] fihArray = FormatableIntHolder.getFormatableIntHolders(hashKeyColumns());
    FormatableArrayHolder hashKeyHolder = new FormatableArrayHolder(fihArray);
    int hashKeyItem = acb.addItem(hashKeyHolder);
    /* Generate the HashTableResultSet:
		 *	arg1: childExpress - Expression for childResultSet
		 *  arg2: searchExpress - Expression for single table predicates
		 *	arg3	: equijoinExpress - Qualifier[] for hash table look up
		 *  arg4: projectExpress - Expression for projection, if any
		 *  arg5: resultSetNumber
		 *  arg6: mapArrayItem - item # for mapping of source columns
		 *  arg7: reuseResult - whether or not the result row can be reused
		 *						(ie, will it always be the same)
		 *	arg8: hashKeyItem - item # for int[] of hash column #s
		 *	arg9: removeDuplicates - don't remove duplicates in hash table (for now)
		 *	arg10: maxInMemoryRowCount - max row size for in-memory hash table
		 *	arg11: initialCapacity - initialCapacity for java.util.Hashtable
		 *	arg12	: loadFactor - loadFactor for java.util.Hashtable
		 *  arg13: estimated row count
		 *  arg14: estimated cost
		 *  arg15: close method
		 */
    acb.pushGetResultSetFactoryExpression(mb);
    if (genChildResultSet)
        childResult.generateResultSet(acb, mb);
    else
        childResult.generate((ActivationClassBuilder) acb, mb);
    /* Get the next ResultSet #, so that we can number this ResultSetNode, its
		 * ResultColumnList and ResultSet.
		 */
    assignResultSetNumber();
    /* Set the point of attachment in all subqueries attached
		 * to this node.
		 */
    if (pSubqueryList != null && pSubqueryList.size() > 0) {
        pSubqueryList.setPointOfAttachment(getResultSetNumber());
        if (SanityManager.DEBUG) {
            SanityManager.ASSERT(pSubqueryList.size() == 0, "pSubqueryList.size() expected to be 0");
        }
    }
    if (rSubqueryList != null && rSubqueryList.size() > 0) {
        rSubqueryList.setPointOfAttachment(getResultSetNumber());
        if (SanityManager.DEBUG) {
            SanityManager.ASSERT(rSubqueryList.size() == 0, "rSubqueryList.size() expected to be 0");
        }
    }
    // Get the final cost estimate based on child's cost.
    setCostEstimate(childResult.getFinalCostEstimate());
    // if there is no searchClause, we just want to pass null.
    if (searchClause == null) {
        mb.pushNull(ClassName.GeneratedMethod);
    } else {
        // this sets up the method and the static field.
        // generates:
        // DataValueDescriptor userExprFun { }
        userExprFun = acb.newUserExprFun();
        // searchClause knows it is returning its value;
        /* generates:
			 *    return <searchClause.generate(acb)>;
			 * and adds it to userExprFun
			 * NOTE: The explicit cast to DataValueDescriptor is required
			 * since the searchClause may simply be a boolean column or subquery
			 * which returns a boolean.  For example:
			 *		where booleanColumn
			 */
        searchClause.generateExpression(acb, userExprFun);
        userExprFun.methodReturn();
        /* PUSHCOMPILER
			userSB.newReturnStatement(searchClause.generateExpression(acb, userSB));
			*/
        // we are done modifying userExprFun, complete it.
        userExprFun.complete();
        // searchClause is used in the final result set as an access of the new static
        // field holding a reference to this new method.
        // generates:
        // ActivationClass.userExprFun
        // which is the static field that "points" to the userExprFun
        // that evaluates the where clause.
        acb.pushMethodReference(mb, userExprFun);
    }
    /* Generate the qualifiers for the look up into
		 * the hash table.
		 */
    joinPredicateList.generateQualifiers(acb, mb, (Optimizable) childResult, false);
    /* Determine whether or not reflection is needed for the projection.
		 * Reflection is not needed if all of the columns map directly to source
		 * columns.
		 */
    if (reflectionNeededForProjection()) {
        // for the resultColumns, we generate a userExprFun
        // that creates a new row from expressions against
        // the current row of the child's result.
        // (Generate optimization: see if we can simply
        // return the current row -- we could, but don't, optimize
        // the function call out and have execution understand
        // that a null function pointer means take the current row
        // as-is, with the performance trade-off as discussed above.)
        /* Generate the Row function for the projection */
        getResultColumns().generateCore(acb, mb, false);
    } else {
        mb.pushNull(ClassName.GeneratedMethod);
    }
    mb.push(getResultSetNumber());
    mb.push(mapArrayItem);
    mb.push(getResultColumns().reusableResult());
    mb.push(hashKeyItem);
    mb.push(false);
    mb.push(-1L);
    mb.push(initialCapacity);
    mb.push(loadFactor);
    mb.push(getCostEstimate().singleScanRowCount());
    mb.push(getCostEstimate().getEstimatedCost());
    mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getHashTableResultSet", ClassName.NoPutResultSet, 14);
}
Also used : FormatableIntHolder(org.apache.derby.iapi.services.io.FormatableIntHolder) FormatableArrayHolder(org.apache.derby.iapi.services.io.FormatableArrayHolder) ReferencedColumnsDescriptorImpl(org.apache.derby.catalog.types.ReferencedColumnsDescriptorImpl) MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

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