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