Search in sources :

Example 6 with MethodBuilder

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

the class InListOperatorNode method generateListAsArray.

/**
 * Generate the code to create an array of DataValueDescriptors that
 * will hold the IN-list values at execution time.  The array gets
 * created in the constructor.  All constant elements in the array
 * are initialized in the constructor.  All non-constant elements,
 * if any, are initialized each time the IN list is evaluated.
 *
 * @param acb The ExpressionClassBuilder for the class we're generating
 * @param mb The MethodBuilder the expression will go into
 */
protected LocalField generateListAsArray(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException {
    int listSize = rightOperandList.size();
    LocalField arrayField = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.DataValueDescriptor + "[]");
    /* Assign the initializer to the DataValueDescriptor[] field */
    MethodBuilder cb = acb.getConstructor();
    cb.pushNewArray(ClassName.DataValueDescriptor, listSize);
    cb.setField(arrayField);
    /* Set the array elements that are constant */
    int numConstants = 0;
    MethodBuilder nonConstantMethod = null;
    MethodBuilder currentConstMethod = cb;
    for (int index = 0; index < listSize; index++) {
        MethodBuilder setArrayMethod;
        if (rightOperandList.elementAt(index) instanceof ConstantNode) {
            numConstants++;
            /*if too many statements are added  to a  method, 
				*size of method can hit  65k limit, which will
				*lead to the class format errors at load time.
				*To avoid this problem, when number of statements added 
				*to a method is > 2048, remaing statements are added to  a new function
				*and called from the function which created the function.
				*See Beetle 5135 or 4293 for further details on this type of problem.
				*/
            if (currentConstMethod.statementNumHitLimit(1)) {
                MethodBuilder genConstantMethod = acb.newGeneratedFun("void", Modifier.PRIVATE);
                currentConstMethod.pushThis();
                currentConstMethod.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, genConstantMethod.getName(), "void", 0);
                // if it is a generate function, close the metod.
                if (currentConstMethod != cb) {
                    currentConstMethod.methodReturn();
                    currentConstMethod.complete();
                }
                currentConstMethod = genConstantMethod;
            }
            setArrayMethod = currentConstMethod;
        } else {
            if (nonConstantMethod == null)
                nonConstantMethod = acb.newGeneratedFun("void", Modifier.PROTECTED);
            setArrayMethod = nonConstantMethod;
        }
        // first arg
        setArrayMethod.getField(arrayField);
        rightOperandList.elementAt(index).generateExpression(acb, setArrayMethod);
        // second arg
        setArrayMethod.upCast(ClassName.DataValueDescriptor);
        setArrayMethod.setArrayElement(index);
    }
    // if a generated function was created to reduce the size of the methods close the functions.
    if (currentConstMethod != cb) {
        currentConstMethod.methodReturn();
        currentConstMethod.complete();
    }
    if (nonConstantMethod != null) {
        nonConstantMethod.methodReturn();
        nonConstantMethod.complete();
        mb.pushThis();
        mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, nonConstantMethod.getName(), "void", 0);
    }
    return arrayField;
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField) MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 7 with MethodBuilder

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

the class ResultColumnList method genCreateRow.

/**
 * Generate the code to create an empty row in the constructor.
 *
 * @param acb					The ACB.
 * @param field					The field for the new row.
 * @param rowAllocatorMethod	The method to call.
 * @param rowAllocatorType		The row type.
 * @param numCols				The number of columns in the row.
 *
 * @exception StandardException		Thrown on error
 */
private void genCreateRow(ExpressionClassBuilder acb, LocalField field, String rowAllocatorMethod, String rowAllocatorType, int numCols) throws StandardException {
    // Create the row in the constructor
    // fieldX = getExecutionFactory().getValueRow(# cols);
    MethodBuilder cb = acb.getConstructor();
    // instance
    acb.pushGetExecutionFactoryExpression(cb);
    cb.push(numCols);
    cb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, rowAllocatorMethod, rowAllocatorType, 1);
    cb.setField(field);
    /* Increase the statement counter in constructor.  Code size in
		 * constructor can become too big (more than 64K) for Java compiler
		 * to handle (beetle 4293).  We set constant columns in other
		 * methods if constructor has too many statements already.
		 */
    // ignore return value
    cb.statementNumHitLimit(1);
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 8 with MethodBuilder

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

the class ResultColumnList method generateEvaluatedRow.

/**
 * <p>
 * Generate the code for a method (userExprFun) which creates a row
 * and, column by column, stuffs it with the evaluated
 * expressions of our ResultColumns. The method returns the
 * stuffed row.
 * </p>
 *
 * This is the method that does the work.
 */
void generateEvaluatedRow(ExpressionClassBuilder acb, MethodBuilder userExprFun, boolean genNulls, boolean forMatchingClause) throws StandardException {
    // generate the function and initializer:
    // private ExecRow fieldX;
    // In the constructor:
    // fieldX = getExecutionFactory().getValueRow(# cols);
    // private ExecRow exprN()
    // {
    // fieldX.setColumn(1, col(1).generateColumn(ps)));
    // ... and so on for each column ...
    // return fieldX;
    // }
    // static Method exprN = method pointer to exprN;
    /* Declare the field */
    LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.ExecRow);
    // Generate the code to create the row in the constructor
    genCreateRow(acb, field, "getValueRow", ClassName.ExecRow, size());
    ResultColumn rc;
    int size = size();
    MethodBuilder cb = acb.getConstructor();
    for (int index = 0; index < size; index++) {
        // generate statements of the form
        // fieldX.setColumn(columnNumber, (DataValueDescriptor) columnExpr);
        // and add them to exprFun.
        rc = elementAt(index);
        /* If we are not generating nulls, then we can skip this RC if
			 * it is simply propagating a column from the source result set.
			 */
        if (!genNulls) {
            ValueNode sourceExpr = rc.getExpression();
            if (sourceExpr instanceof VirtualColumnNode && !(((VirtualColumnNode) sourceExpr).getCorrelated())) {
                continue;
            }
            // then pick up that value
            if (rc.getJoinResultSet() != null) {
                // We are dealing with a join column for
                // RIGHT OUTER JOIN with USING/NATURAL eg
                // select c from t1 right join t2 using (c)
                // We are talking about column c as in "select c"
                ResultColumnList jnRCL = rc.getJoinResultSet().getResultColumns();
                int joinResultSetNumber = rc.getJoinResultSet().getResultSetNumber();
                // We need to know the column positions of left
                // table's join column and right table's join
                // column to generate the code explained above
                int virtualColumnIdRightTable = -1;
                int virtualColumnIdLeftTable = -1;
                for (ResultColumn joinColumn : jnRCL) {
                    if (joinColumn.getName().equals(rc.getUnderlyingOrAliasName())) {
                        if (joinColumn.isRightOuterJoinUsingClause())
                            virtualColumnIdRightTable = joinColumn.getVirtualColumnId();
                        else
                            virtualColumnIdLeftTable = joinColumn.getVirtualColumnId();
                    }
                }
                // instance
                userExprFun.getField(field);
                // arg1
                userExprFun.push(index + 1);
                String resultTypeName = getTypeCompiler(DataTypeDescriptor.getBuiltInDataTypeDescriptor(Types.BOOLEAN).getTypeId()).interfaceName();
                String receiverType = ClassName.DataValueDescriptor;
                // Our plan is to generate DERBY-4631
                // if(lefTablJoinColumnValue is null)
                // then
                // use rightTablJoinColumnValue
                // else
                // use lefTablJoinColumnValue
                // Following will generate
                // if(lefTablJoinColumnValue is null)
                acb.pushColumnReference(userExprFun, joinResultSetNumber, virtualColumnIdLeftTable);
                userExprFun.cast(rc.getTypeCompiler().interfaceName());
                userExprFun.cast(receiverType);
                userExprFun.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "isNullOp", resultTypeName, 0);
                // Then call generateExpression on left Table's column
                userExprFun.cast(ClassName.BooleanDataValue);
                userExprFun.push(true);
                userExprFun.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "equals", "boolean", 1);
                // Following will generate
                // then
                // use rightTablJoinColumnValue
                userExprFun.conditionalIf();
                acb.pushColumnReference(userExprFun, joinResultSetNumber, virtualColumnIdRightTable);
                userExprFun.cast(rc.getTypeCompiler().interfaceName());
                // Following will generate
                // else
                // use lefTablJoinColumnValue
                userExprFun.startElseCode();
                acb.pushColumnReference(userExprFun, joinResultSetNumber, virtualColumnIdLeftTable);
                userExprFun.cast(rc.getTypeCompiler().interfaceName());
                userExprFun.completeConditional();
                userExprFun.cast(ClassName.DataValueDescriptor);
                userExprFun.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2);
                continue;
            }
            if (!forMatchingClause) {
                if (sourceExpr instanceof ColumnReference && !(((ColumnReference) sourceExpr).getCorrelated())) {
                    continue;
                }
            }
        }
        // row add is 1-based, and iterator index is 0-based
        if (SanityManager.DEBUG) {
            if (index + 1 != rc.getVirtualColumnId()) {
                SanityManager.THROWASSERT("VirtualColumnId (" + rc.getVirtualColumnId() + ") does not agree with position within Vector (" + (index + 1) + ")");
            }
        }
        // 
        if (rc.hasGenerationClause()) {
            ValueNode expr = rc.getExpression();
            if ((expr != null) && !(expr instanceof VirtualColumnNode)) {
                continue;
            }
        }
        /* SPECIAL CASE:  Expression is a non-null constant.
			 *	Generate the setColumn() call in the constructor
			 *  so that it will only be executed once per instantiation.
			 *
		 	 * Increase the statement counter in constructor.  Code size in
		 	 * constructor can become too big (more than 64K) for Java compiler
		 	 * to handle (beetle 4293).  We set constant columns in other
		 	 * methods if constructor has too many statements already.
		 	 */
        if ((!genNulls) && (rc.getExpression() instanceof ConstantNode) && !((ConstantNode) rc.getExpression()).isNull() && !cb.statementNumHitLimit(1)) {
            // instance
            cb.getField(field);
            // first arg;
            cb.push(index + 1);
            rc.generateExpression(acb, cb);
            // second arg
            cb.cast(ClassName.DataValueDescriptor);
            cb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2);
            continue;
        }
        // instance
        userExprFun.getField(field);
        // arg1
        userExprFun.push(index + 1);
        /* We want to reuse the null values instead of doing a new each time
			 * if the caller said to generate nulls or the underlying expression
			 * is a typed null value.
			 */
        boolean needDVDCast = true;
        if (rc.isAutoincrementGenerated()) {
            // (com.ibm.db2j.impl... DataValueDescriptor)
            // this.getSetAutoincValue(column_number)
            userExprFun.pushThis();
            userExprFun.push(rc.getColumnPosition());
            userExprFun.push(rc.getTableColumnDescriptor().getAutoincInc());
            userExprFun.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "getSetAutoincrementValue", ClassName.DataValueDescriptor, 2);
            needDVDCast = false;
        } else if (genNulls || ((rc.getExpression() instanceof ConstantNode) && ((ConstantNode) rc.getExpression()).isNull())) {
            userExprFun.getField(field);
            userExprFun.push(index + 1);
            userExprFun.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "getColumn", ClassName.DataValueDescriptor, // the express
            1);
            acb.generateNullWithExpress(userExprFun, rc.getTypeCompiler(), rc.getTypeServices().getCollationType());
        } else {
            rc.generateExpression(acb, userExprFun);
        }
        if (needDVDCast)
            userExprFun.cast(ClassName.DataValueDescriptor);
        userExprFun.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2);
    }
    userExprFun.getField(field);
    userExprFun.methodReturn();
    // we are now done modifying userExprFun
    userExprFun.complete();
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField) MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 9 with MethodBuilder

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

the class RowCountNode method generateExprFun.

private void generateExprFun(ExpressionClassBuilder ecb, MethodBuilder mb, ValueNode vn) throws StandardException {
    // Generates:
    // Object exprFun { }
    MethodBuilder exprFun = ecb.newExprFun();
    /* generates:
         *    return  <dynamic parameter.generate(ecb)>;
         * and adds it to exprFun
         */
    vn.generateExpression(ecb, exprFun);
    exprFun.methodReturn();
    // we are done modifying exprFun, complete it.
    exprFun.complete();
    // Pass in the method that will be used to evaluates the dynamic
    // parameter in RowCountResultSet.
    ecb.pushMethodReference(mb, exprFun);
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 10 with MethodBuilder

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

the class SQLToJavaValueNode method generateJavaValue.

/**
 * Generate code to cast the SQLValue to a Java value.
 *
 * @param acb	The ExpressionClassBuilder for the class being built
 * @param mbex	The method the expression will go into
 *
 * @exception StandardException		Thrown on error
 */
private void generateJavaValue(ExpressionClassBuilder acb, MethodBuilder mbex) throws StandardException {
    /* If this is a conversion to a primitive type, then call the
		 * appropriate method for getting the primitive value and
		 * cast it to the primitive type. 
		 * NOTE: We first call Activation.nullToPrimitiveTest(),
		 * which will throw a StandardException if the value is null
		 */
    if (isPrimitiveType() || mustCastToPrimitive()) {
        String primitiveTN = value.getTypeCompiler().getCorrespondingPrimitiveTypeName();
        /* Put the code to check if the object is null and to
			 * get the primitive value in a method call.  This is
			 * necessary because we are generating an expression here and
			 * cannot have multiple statements.
			 * The method call will take SQLValue as a parameter.
			 */
        String[] pd = new String[1];
        // parameter "param1"
        pd[0] = getSQLValueInterfaceName();
        MethodBuilder mb = acb.newGeneratedFun(primitiveTN, Modifier.PRIVATE, pd);
        mb.getParameter(0);
        if (returnsNullOnNullState != null) {
            generateReturnsNullOnNullCheck(mb);
        } else {
            mb.dup();
            mb.upCast(ClassName.DataValueDescriptor);
            mb.push(primitiveTN);
            mb.callMethod(VMOpcode.INVOKESTATIC, ClassName.BaseActivation, "nullToPrimitiveTest", "void", 2);
        }
        // stack is dvd
        /* Generate the code to get the primitive value */
        mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, value.getTypeCompiler().getPrimitiveMethodName(), primitiveTN, 0);
        mb.methodReturn();
        mb.complete();
        /* Generate the call to the new method, with the parameter */
        mbex.pushThis();
        // caller pushed out parameter
        mbex.swap();
        mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb.getName(), primitiveTN, 1);
    } else {
        if (returnsNullOnNullState != null)
            generateReturnsNullOnNullCheck(mbex);
        /* Call getObject() to get the right type of Java value */
        mbex.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, "getObject", "java.lang.Object", 0);
        mbex.cast(value.getTypeId().getCorrespondingJavaTypeName());
    }
}
Also used : 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