Search in sources :

Example 11 with LocalField

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

the class BinaryOperatorNode method generateExpression.

/**
 * Do code generation for this binary operator.
 *
 * @param acb	The ExpressionClassBuilder for the class we're generating
 * @param mb	The method the code to place the code
 *
 * @exception StandardException		Thrown on error
 */
@Override
void generateExpression(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException {
    /* If this BinaryOperatorNode was created as a part of an IN-list
		 * "probe predicate" then we do not want to generate the relational
		 * operator itself; instead we want to generate the underlying
		 * IN-list for which this operator node was created.
		 *
		 * We'll get here in situations where the optimizer chooses a plan
		 * for which the probe predicate is *not* a useful start/stop key
		 * and thus is not being used for execution-time index probing.
		 * In this case we are effectively "reverting" the probe predicate
		 * back to the InListOperatorNode from which it was created.  Or put
		 * another way, we are "giving up" on index multi-probing and simply
		 * generating the original IN-list as a regular restriction.
		 */
    if (this instanceof BinaryRelationalOperatorNode) {
        InListOperatorNode ilon = ((BinaryRelationalOperatorNode) this).getInListOp();
        if (ilon != null) {
            ilon.generateExpression(acb, mb);
            return;
        }
    }
    String resultTypeName;
    String receiverType;
    /*
** if i have a operator.getOrderableType() == constant, then just cache 
** it in a field.  if i have QUERY_INVARIANT, then it would be good to
** cache it in something that is initialized each execution,
** but how?
*/
    // The number of arguments to pass to the method that implements the
    // operator, depends on the type of the operator.
    int numArgs;
    // If we're dealing with XMLEXISTS or XMLQUERY, there is some
    // additional work to be done.
    boolean xmlGen = (kind == K_XMLQUERY) || (kind == K_XMLEXISTS);
    /*
		** The receiver is the operand with the higher type precedence.
		** Like always makes the left the receiver.
		**
		*/
    if (leftOperand.getTypeId().typePrecedence() > rightOperand.getTypeId().typePrecedence()) {
        receiver = leftOperand;
        /*
			** let the receiver type be determined by an
			** overridable method so that if methods are
			** not implemented on the lowest interface of
			** a class, they can note that in the implementation
			** of the node that uses the method.
			*/
        receiverType = (kind == K_BASE) ? getReceiverInterfaceName() : leftInterfaceType;
        /*
			** Generate (with <left expression> only being evaluated once)
			**
			**	<left expression>.method(<left expression>, <right expression>...)
			*/
        leftOperand.generateExpression(acb, mb);
        // cast the method instance
        mb.cast(receiverType);
        // stack: left
        mb.dup();
        mb.cast(leftInterfaceType);
        // stack: left, left
        rightOperand.generateExpression(acb, mb);
        // second arg with cast
        mb.cast(rightInterfaceType);
        // stack: left, left, right
        // We've pushed two arguments
        numArgs = 2;
    } else {
        receiver = rightOperand;
        /*
			** let the receiver type be determined by an
			** overridable method so that if methods are
			** not implemented on the lowest interface of
			** a class, they can note that in the implementation
			** of the node that uses the method.
			*/
        receiverType = (kind == K_BASE) ? getReceiverInterfaceName() : rightInterfaceType;
        /*
			** Generate (with <right expression> only being evaluated once)
			**
			**	<right expression>.method(<left expression>, <right expression>)
			**
			** UNLESS we're generating an XML operator such as XMLEXISTS.
			** In that case we want to generate
			** 
			**  <right expression>.method(sqlXmlUtil)
			*/
        rightOperand.generateExpression(acb, mb);
        // cast the method instance
        mb.cast(receiverType);
        if (xmlGen) {
            // Push one argument (the SqlXmlUtil instance)
            numArgs = 1;
            pushSqlXmlUtil(acb, mb, xmlQuery, operator);
        // stack: right,sqlXmlUtil
        } else {
            // Push two arguments (left, right)
            numArgs = 2;
            mb.dup();
            mb.cast(rightInterfaceType);
            // stack: right,right
            leftOperand.generateExpression(acb, mb);
            // second arg with cast
            mb.cast(leftInterfaceType);
            // stack: right,right,left
            mb.swap();
        // stack: right,left,right
        }
    }
    /* Figure out the result type name */
    resultTypeName = (kind == K_BASE) ? getTypeCompiler().interfaceName() : resultInterfaceType;
    // Boolean return types don't need a result field. For other types,
    // allocate an object for re-use to hold the result of the operator.
    LocalField resultField = getTypeId().isBooleanTypeId() ? null : acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName);
    // Push the result field onto the stack, if there is a result field.
    if (resultField != null) {
        /*
			** Call the method for this operator.
			*/
        // third arg
        mb.getField(resultField);
        // Adjust number of arguments for the result field
        numArgs++;
        /* pass statically calculated scale to decimal divide method to make
			 * result set scale consistent, beetle 3901
			 */
        int jdbcType;
        if ((getTypeServices() != null) && ((jdbcType = getTypeServices().getJDBCTypeId()) == java.sql.Types.DECIMAL || jdbcType == java.sql.Types.NUMERIC) && operator.equals("/")) {
            // 4th arg
            mb.push(getTypeServices().getScale());
            numArgs++;
        }
    }
    mb.callMethod(VMOpcode.INVOKEINTERFACE, receiverType, methodName, resultTypeName, numArgs);
    // Store the result of the method call, if there is a result field.
    if (resultField != null) {
        // the need for following if was realized while fixing bug 5704 where decimal*decimal was resulting an overflow value but we were not detecting it
        if (// since result type is numeric variable length, generate setWidth code.
        getTypeId().variableLength()) {
            if (getTypeId().isNumericTypeId()) {
                // to leave the DataValueDescriptor value on the stack, since setWidth is void
                mb.dup();
                mb.push(getTypeServices().getPrecision());
                mb.push(getTypeServices().getScale());
                mb.push(true);
                mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, "setWidth", "void", 3);
            }
        }
        /*
			** Store the result of the method call in the field, so we can re-use
			** the object.
			*/
        mb.putField(resultField);
    }
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 12 with LocalField

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

the class CastNode method genDataValueConversion.

private void genDataValueConversion(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException {
    MethodBuilder acbConstructor = acb.getConstructor();
    String resultTypeName = getTypeCompiler().interfaceName();
    /* field = method call */
    /* Allocate an object for re-use to hold the result of the operator */
    LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, resultTypeName);
    /*
		** Store the result of the method call in the field, so we can re-use
		** the object.
		*/
    acb.generateNull(acbConstructor, getTypeCompiler(getTypeId()), getTypeServices().getCollationType());
    acbConstructor.setField(field);
    if (!sourceCTI.userType() && !getTypeId().userType()) {
        // targetDVD reference for the setValue method call
        mb.getField(field);
        mb.swap();
        mb.upCast(ClassName.DataValueDescriptor);
        mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, "setValue", "void", 1);
    } else {
        /* 
			** generate: expr.getObject()
			*/
        mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, "getObject", "java.lang.Object", 0);
        // castExpr
        // instance for the setValue/setObjectForCast method call
        mb.getField(field);
        // push it before the value
        mb.swap();
        /*
			** We are casting a java type, generate:
			**
			**		DataValueDescriptor.setObjectForCast(java.lang.Object castExpr, boolean instanceOfExpr, destinationClassName)
			** where instanceOfExpr is "source instanceof destinationClass".
			**
			*/
        String destinationType = getTypeId().getCorrespondingJavaTypeName();
        // at this point method instance and cast result are on the stack
        // we duplicate the cast value in order to perform the instanceof check
        mb.dup();
        mb.isInstanceOf(destinationType);
        mb.push(destinationType);
        mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.DataValueDescriptor, "setObjectForCast", "void", 3);
    }
    mb.getField(field);
    /* 
		** If we are casting to a variable length datatype, we
		** have to make sure we have set it to the correct
		** length.
		*/
    if (getTypeId().variableLength()) {
        boolean isNumber = getTypeId().isNumericTypeId();
        // to leave the DataValueDescriptor value on the stack, since setWidth is void
        mb.dup();
        /* setWidth() is on VSDV - upcast since
			 * decimal implements subinterface
			 * of VSDV.
			 */
        mb.push(isNumber ? getTypeServices().getPrecision() : getTypeServices().getMaximumWidth());
        mb.push(getTypeServices().getScale());
        mb.push(!sourceCTI.variableLength() || isNumber || assignmentSemantics);
        mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.VariableSizeDataValue, "setWidth", "void", 3);
    }
}
Also used : MethodBuilder(org.apache.derby.iapi.services.compiler.MethodBuilder) LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 13 with LocalField

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

the class ExpressionClassBuilder method getCurrentDateExpression.

// /////////////////////////////////////////////////////////////////////
// 
// CURRENT DATE/TIME SUPPORT
// 
// /////////////////////////////////////////////////////////////////////
/**
 *		This utility method returns an expression for CURRENT_DATE.
 *		Get the expression this way, because the activation needs to
 *		generate support information for CURRENT_DATE,
 *		that would otherwise be painful to create manually.
 */
void getCurrentDateExpression(MethodBuilder mb) {
    // do any needed setup
    LocalField lf = getCurrentSetup();
    // generated Java:
    // this.cdt.getCurrentDate();
    mb.getField(lf);
    mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, "getCurrentDate", "java.sql.Date", 0);
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 14 with LocalField

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

the class ExpressionClassBuilder method getCurrentTimeExpression.

/**
 *		This utility method returns an expression for CURRENT_TIME.
 *		Get the expression this way, because the activation needs to
 *		generate support information for CURRENT_TIME,
 *		that would otherwise be painful to create manually.
 */
void getCurrentTimeExpression(MethodBuilder mb) {
    // do any needed setup
    LocalField lf = getCurrentSetup();
    // generated Java:
    // this.cdt.getCurrentTime();
    mb.getField(lf);
    mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, "getCurrentTime", "java.sql.Time", 0);
}
Also used : LocalField(org.apache.derby.iapi.services.compiler.LocalField)

Example 15 with LocalField

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

the class ExpressionClassBuilder method getCurrentTimestampExpression.

/**
 *		This utility method generates an expression for CURRENT_TIMESTAMP.
 *		Get the expression this way, because the activation needs to
 *		generate support information for CURRENT_TIMESTAMP,
 *		that would otherwise be painful to create manually.
 */
void getCurrentTimestampExpression(MethodBuilder mb) {
    // do any needed setup
    LocalField lf = getCurrentSetup();
    // generated Java:
    // this.cdt.getCurrentTimestamp();
    mb.getField(lf);
    mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, "getCurrentTimestamp", "java.sql.Timestamp", 0);
}
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