use of org.apache.derby.iapi.services.compiler.MethodBuilder 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);
}
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class BinaryRelationalOperatorNode method generateQualMethod.
/**
* @exception StandardException Thrown on error
*/
public void generateQualMethod(ExpressionClassBuilderInterface acbi, MethodBuilder mb, Optimizable optTable) throws StandardException {
ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi;
/* Generate a method that returns the expression */
MethodBuilder qualMethod = acb.newUserExprFun();
/*
** Generate the expression that's on the opposite side
** of the key column
*/
if (keyColumnOnLeft(optTable)) {
rightOperand.generateExpression(acb, qualMethod);
} else {
leftOperand.generateExpression(acb, qualMethod);
}
qualMethod.methodReturn();
qualMethod.complete();
/* push an expression that evaluates to the GeneratedMethod */
acb.pushMethodReference(mb, qualMethod);
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class DMLModStatementNode method generateCheckConstraints.
/**
* Generate the code to evaluate a tree of CHECK CONSTRAINTS.
*
* @param checkConstraints Bound query tree of ANDed check constraints.
* @param ecb Expression Class Builder
*
* @exception StandardException Thrown on error
*/
public void generateCheckConstraints(ValueNode checkConstraints, ExpressionClassBuilder ecb, MethodBuilder mb) throws StandardException {
// if there is no check constraint, we just want to pass null.
if (checkConstraints == null) {
mb.pushNull(ClassName.GeneratedMethod);
} else {
MethodBuilder userExprFun = generateCheckConstraints(checkConstraints, ecb);
// check constraint is used in the final result set
// as an access of the new static
// field holding a reference to this new method.
ecb.pushMethodReference(mb, userExprFun);
}
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class DMLModStatementNode method generateCheckConstraints.
/**
* Generate a method to evaluate a tree of CHECK CONSTRAINTS.
*
* @param checkConstraints Bound query tree of ANDed check constraints.
* @param ecb Expression Class Builder
*
* @exception StandardException Thrown on error
*/
public MethodBuilder generateCheckConstraints(ValueNode checkConstraints, ExpressionClassBuilder ecb) throws StandardException {
// this sets up the method and the static field.
// generates:
// java.lang.Object userExprFun { }
MethodBuilder userExprFun = ecb.newUserExprFun();
// check constraint knows it is returning its value;
/* generates:
* return <checkExpress.generate(ecb)>;
* and adds it to userExprFun
*/
checkConstraints.generateExpression(ecb, userExprFun);
userExprFun.methodReturn();
// we are done modifying userExprFun, complete it.
userExprFun.complete();
return userExprFun;
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class DMLModStatementNode method generateGenerationClauses.
/**
* Generate a method to compute all of the generation clauses in a row.
*
* @param rcl describes the row of expressions to be put into the bas table
* @param rsNumber index of base table into array of ResultSets
* @param isUpdate true if this is for an UPDATE statement
* @param ecb code generation state variable
*/
private MethodBuilder generateGenerationClauses(ResultColumnList rcl, int rsNumber, boolean isUpdate, ExpressionClassBuilder ecb) throws StandardException {
// this sets up the method and the static field.
// generates:
// java.lang.Object userExprFun( ) { }
MethodBuilder userExprFun = ecb.newUserExprFun();
/* Push the the current row onto the stack. */
userExprFun.pushThis();
userExprFun.push(rsNumber);
userExprFun.callMethod(VMOpcode.INVOKEVIRTUAL, ClassName.BaseActivation, "getCurrentRow", ClassName.Row, 1);
// Loop through the result columns, computing generated columns
// as we go.
int size = rcl.size();
int startColumn = 0;
// the before-images of the columns.
if (isUpdate) {
// throw away the last cell in the row, which is the row id
startColumn = size - 1;
startColumn = startColumn / 2;
}
for (int i = startColumn; i < size; i++) {
ResultColumn rc = rcl.elementAt(i);
if (!rc.hasGenerationClause()) {
continue;
}
// instance (current row)
userExprFun.dup();
// arg1
userExprFun.push(i + 1);
// actually optimized so column references still need result set numbers
if (inMatchingClause()) {
CollectNodesVisitor<ColumnReference> getCRs = new CollectNodesVisitor<ColumnReference>(ColumnReference.class);
rc.accept(getCRs);
for (ColumnReference cr : getCRs.getList()) {
cr.getSource().setResultSetNumber(rsNumber);
}
}
rc.generateExpression(ecb, userExprFun);
userExprFun.cast(ClassName.DataValueDescriptor);
userExprFun.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2);
}
/* generates:
* return;
* And adds it to userExprFun
*/
userExprFun.methodReturn();
// we are done modifying userExprFun, complete it.
userExprFun.complete();
return userExprFun;
}
Aggregations