Search in sources :

Example 26 with LocalField

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

the class CurrentRowLocationNode method generateExpression.

/**
 * CurrentRowLocationNode is used in updates and deletes.  See generate() in
 * UpdateNode and DeleteNode to get the full overview of generate().  This
 * class is responsible for generating the method that will return the RowLocation
 * for the next row to be updated or deleted.
 *
 * This routine will generate a method of the form:
 *
 *		private SQLRef	fieldx;
 *
 *		...
 *
 *      protected DataValueDescriptor exprx()
 *				throws StandardException
 *		{
 *			return fieldx = <SQLRefConstructor>(
 *									"result set member".getRowLocation(),
 *									fieldx);
 *		}
 * and return the generated code:
 *    exprx()
 *
 * ("result set member" is a member of the generated class added by UpdateNode or
 * DeleteNode.)
 * This exprx function is used within another exprx function,
 * and so doesn't need a static field or to be public; but
 * at present, it has both.
 *
 * fieldx is a generated field that is initialized to null when the
 * activation is constructed.  getSQLRef will re-use fieldx on calls
 * after the first call, rather than allocate a new SQLRef for each call.
 *
 * @param acb	The ExpressionClassBuilder for the class being built
 *
 * @exception StandardException		Thrown on error
 */
@Override
void generateExpression(ExpressionClassBuilder acb, MethodBuilder mbex) throws StandardException {
    /* Generate a new method */
    /* only used within the other exprFuns, so can be private */
    MethodBuilder mb = acb.newGeneratedFun(ClassName.DataValueDescriptor, Modifier.PROTECTED);
    /* Allocate an object for re-use to hold the result of the operator */
    LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.RefDataValue);
    /* Fill in the body of the method
		 * generates:
		 *    return TypeFactory.getSQLRef(this.ROWLOCATIONSCANRESULTSET.getRowLocation());
		 * and adds it to exprFun
		 */
    mb.pushThis();
    mb.getField((String) null, acb.getRowLocationScanResultSetName(), ClassName.CursorResultSet);
    mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getRowLocation", ClassName.RowLocation, 0);
    acb.generateDataValue(mb, getTypeCompiler(), getTypeServices().getCollationType(), field);
    /*
		** Store the result of the method call in the field, so we can re-use
		** the object.
		*/
    mb.putField(field);
    /* Stuff the full expression into a return statement and add that to the
		 * body of the new method.
		 */
    mb.methodReturn();
    // complete the method
    mb.complete();
    /* Generate the call to the new method */
    mbex.pushThis();
    mbex.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mb.getName(), ClassName.DataValueDescriptor, 0);
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder) LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 27 with LocalField

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

the class CoalesceFunctionNode method generateExpression.

/**
 * Do code generation for coalesce/value
 *
 * @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 argumentsListSize = argumentsList.size();
    String receiverType = ClassName.DataValueDescriptor;
    String argumentsListInterfaceType = ClassName.DataValueDescriptor + "[]";
    // Generate the code to build the array
    LocalField arrayField = acb.newFieldDeclaration(Modifier.PRIVATE, argumentsListInterfaceType);
    /* The array gets created in the constructor.
		 * All constant elements in the array are initialized
		 * in the constructor.  
		 */
    /* Assign the initializer to the DataValueDescriptor[] field */
    MethodBuilder cb = acb.getConstructor();
    cb.pushNewArray(ClassName.DataValueDescriptor, argumentsListSize);
    cb.setField(arrayField);
    /* Set the array elements that are constant */
    int numConstants = 0;
    MethodBuilder nonConstantMethod = null;
    MethodBuilder currentConstMethod = cb;
    for (int index = 0; index < argumentsListSize; index++) {
        MethodBuilder setArrayMethod;
        if (argumentsList.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;
        }
        setArrayMethod.getField(arrayField);
        argumentsList.elementAt(index).generateExpression(acb, setArrayMethod);
        setArrayMethod.upCast(receiverType);
        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);
    }
    /*
		**  Call the method for coalesce/value function.
		**	First generate following
		**	<first non-param argument in the list>.method(<all the arguments>, <resultType>)
		**	Next, if we are dealing with result type that is variable length, then generate a call to setWidth.
		*/
    // coalesce will be called on this non-parameter argument
    argumentsList.elementAt(firstNonParameterNodeIdx).generateExpression(acb, mb);
    mb.upCast(ClassName.DataValueDescriptor);
    // first arg to the coalesce function
    mb.getField(arrayField);
    // Following is for the second arg. This arg will be used to pass the return value.
    // COALESCE method expects this to be initialized to NULL SQLxxx type object.
    LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, receiverType);
    acb.generateNull(mb, getTypeCompiler(), getTypeServices().getCollationType());
    mb.upCast(ClassName.DataValueDescriptor);
    mb.putField(field);
    mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, "coalesce", receiverType, 2);
    if (// since result type is variable length, generate setWidth code.
    getTypeId().variableLength()) {
        boolean isNumber = getTypeId().isNumericTypeId();
        // to leave the DataValueDescriptor value on the stack, since setWidth is void
        mb.dup();
        mb.push(isNumber ? getTypeServices().getPrecision() : getTypeServices().getMaximumWidth());
        mb.push(getTypeServices().getScale());
        mb.push(true);
        mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, "setWidth", "void", 3);
    }
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField) MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 28 with LocalField

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

the class DeleteNode method generate.

/**
 * Code generation for delete.
 * The generated code will contain:
 *		o  A static member for the (xxx)ResultSet with the RowLocations
 *		o  The static member will be assigned the appropriate ResultSet within
 *		   the nested calls to get the ResultSets.  (The appropriate cast to the
 *		   (xxx)ResultSet will be generated.)
 *		o  The CurrentRowLocation() in SelectNode's select list will generate
 *		   a new method for returning the RowLocation as well as a call to
 *		   that method which will be stuffed in the call to the
 *		    ProjectRestrictResultSet.
 *      o In case of referential actions, this function generate an
 *        array of resultsets on its dependent tables.
 *
 * @param acb	The ActivationClassBuilder for the class being built
 * @param mb	The execute() method to be built
 *
 * @exception StandardException		Thrown on error
 */
@Override
void generate(ActivationClassBuilder acb, MethodBuilder mb) throws StandardException {
    // If the DML is on the temporary table, generate the code to
    // mark temporary table as modified in the current UOW. After
    // DERBY-827 this must be done in execute() since
    // createResultSet() will only be called once.
    generateCodeForTemporaryTable(acb);
    /* generate the parameters */
    if (!isDependentTable)
        generateParameterValueSet(acb);
    acb.pushGetResultSetFactoryExpression(mb);
    acb.newRowLocationScanResultSetName();
    // arg 1
    if (inMatchingClause()) {
        matchingClause.generateResultSetField(acb, mb);
    } else {
        resultSet.generate(acb, mb);
    }
    String resultSetGetter;
    int argCount;
    String parentResultSetId;
    // Base table
    if (targetTableDescriptor != null) {
        /* Create the declaration for the scan ResultSet which generates the
			 * RowLocations to be deleted.
	 		 * Note that the field cannot be static because there
			 * can be multiple activations of the same activation class,
			 * and they can't share this field.  Only exprN fields can
			 * be shared (or, more generally, read-only fields).
			 * RESOLVE - Need to deal with the type of the field.
			 */
        acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.CursorResultSet, acb.getRowLocationScanResultSetName());
        if (cascadeDelete || isDependentTable) {
            resultSetGetter = "getDeleteCascadeResultSet";
            argCount = 4;
        } else {
            resultSetGetter = "getDeleteResultSet";
            argCount = 1;
        }
    } else {
        argCount = 1;
        resultSetGetter = "getDeleteVTIResultSet";
    }
    if (isDependentTable) {
        mb.push(acb.addItem(makeConstantAction()));
    } else {
        if (cascadeDelete) {
            // root table.
            mb.push(-1);
        }
    }
    String resultSetArrayType = ClassName.ResultSet + "[]";
    if (cascadeDelete) {
        parentResultSetId = targetTableDescriptor.getSchemaName() + "." + targetTableDescriptor.getName();
        // Generate the code to build the array
        LocalField arrayField = acb.newFieldDeclaration(Modifier.PRIVATE, resultSetArrayType);
        // new ResultSet[size]
        mb.pushNewArray(ClassName.ResultSet, dependentNodes.length);
        mb.setField(arrayField);
        for (int index = 0; index < dependentNodes.length; index++) {
            dependentNodes[index].setRefActionInfo(fkIndexConglomNumbers[index], fkColArrays[index], parentResultSetId, true);
            // first arg (resultset array reference)
            mb.getField(arrayField);
            /*beetle:5360 : 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 (mb.statementNumHitLimit(10)) {
                MethodBuilder dmb = acb.newGeneratedFun(ClassName.ResultSet, Modifier.PRIVATE);
                // generates the resultset expression
                dependentNodes[index].generate(acb, dmb);
                dmb.methodReturn();
                dmb.complete();
                /* Generate the call to the new method */
                mb.pushThis();
                // second arg will be generated by this call
                mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, dmb.getName(), ClassName.ResultSet, 0);
            } else {
                // generates the resultset expression
                dependentNodes[index].generate(acb, mb);
            }
            mb.setArrayElement(index);
        }
        // fourth argument - array reference
        mb.getField(arrayField);
    } else {
        if (isDependentTable) {
            // No dependent tables for this table
            mb.pushNull(resultSetArrayType);
        }
    }
    if (cascadeDelete || isDependentTable) {
        parentResultSetId = targetTableDescriptor.getSchemaName() + "." + targetTableDescriptor.getName();
        mb.push(parentResultSetId);
    }
    mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, resultSetGetter, ClassName.ResultSet, argCount);
    if (!isDependentTable && cascadeDelete) {
        int numResultSets = acb.getRowCount();
        if (numResultSets > 0) {
            // generate activation.raParentResultSets = new NoPutResultSet[size]
            MethodBuilder constructor = acb.getConstructor();
            constructor.pushThis();
            constructor.pushNewArray(ClassName.CursorResultSet, numResultSets);
            constructor.putField(ClassName.BaseActivation, "raParentResultSets", ClassName.CursorResultSet + "[]");
            constructor.endStatement();
        }
    }
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField) MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder)

Example 29 with LocalField

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

the class MatchingClauseNode method generateResultSetField.

/**
 * <p>
 * Adds a field to the generated class to hold the ResultSet of "then" rows
 * which drive the INSERT/UPDATE/DELETE action. Generates code to push
 * the contents of that field onto the stack.
 * </p>
 */
void generateResultSetField(ActivationClassBuilder acb, MethodBuilder mb) throws StandardException {
    _resultSetFieldName = "mergeResultSetField_" + _clauseNumber;
    // make the field public so we can stuff it at execution time
    LocalField resultSetField = acb.newFieldDeclaration(Modifier.PUBLIC, ClassName.NoPutResultSet, _resultSetFieldName);
    // 
    // At runtime, MatchingClauseConstantAction.executeConstantAction()
    // will stuff the resultSetField with the temporary table which collects
    // the rows relevant to this action. We want to push the value of resultSetField
    // onto the stack, where it will be the ResultSet argument to the constructor
    // of the actual INSERT/UPDATE/DELETE action.
    // 
    mb.getField(resultSetField);
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 30 with LocalField

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

the class NewInvocationNode method generateExpression.

/**
 * Do code generation for this method call
 *
 * @param acb	The ExpressionClassBuilder for the class we're generating
 * @param mb	The method the expression will go into
 *
 * @exception StandardException		Thrown on error
 */
void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException {
    /* If this node is for an ungrouped aggregator, 
		 * then we generate a conditional
		 * wrapper so that we only new the aggregator once.
		 *		(fx == null) ? fx = new ... : fx
		 */
    LocalField objectFieldLF = null;
    if (singleInstantiation) {
        /* Declare the field */
        objectFieldLF = acb.newFieldDeclaration(Modifier.PRIVATE, javaClassName);
        // now we fill in the body of the conditional
        mb.getField(objectFieldLF);
        mb.conditionalIfNull();
    }
    mb.pushNewStart(javaClassName);
    int nargs = generateParameters(acb, mb);
    mb.pushNewComplete(nargs);
    if (singleInstantiation) {
        mb.putField(objectFieldLF);
        mb.startElseCode();
        mb.getField(objectFieldLF);
        mb.completeConditional();
    }
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField)

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