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;
}
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);
}
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();
}
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);
}
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());
}
}
Aggregations