use of org.apache.derby.iapi.services.compiler.MethodBuilder 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.MethodBuilder in project derby by apache.
the class JoinNode method getJoinArguments.
/**
* Get the arguments to the join result set.
*
* @param acb The ActivationClassBuilder for the class we're building.
* @param mb the method the generated code is going into
* @param joinClause The join clause, if any
*
* @return The array of arguments to the join result set
*
* @exception StandardException Thrown on error
*/
private int getJoinArguments(ActivationClassBuilder acb, MethodBuilder mb, ValueNode joinClause) throws StandardException {
int numArgs = getNumJoinArguments();
// arg 1
leftResultSet.generate(acb, mb);
// arg 2
mb.push(leftResultSet.getResultColumns().size());
// arg 3
rightResultSet.generate(acb, mb);
// arg 4
mb.push(rightResultSet.getResultColumns().size());
// Get our final cost estimate based on child estimates.
setCostEstimate(getFinalCostEstimate());
// if there is no join clause, we just pass a null Expression.
if (joinClause == null) {
// arg 5
mb.pushNull(ClassName.GeneratedMethod);
} else {
// this sets up the method and the static field.
// generates:
// Object userExprFun { }
MethodBuilder userExprFun = acb.newUserExprFun();
// join clause knows it is returning its value;
/* generates:
* return <joinClause.generate(acb)>;
* and adds it to userExprFun
*/
joinClause.generate(acb, userExprFun);
userExprFun.methodReturn();
// we are done modifying userExprFun, complete it.
userExprFun.complete();
// join clause is used in the final result set as an access of the new static
// field holding a reference to this new method.
// generates:
// ActivationClass.userExprFun
// which is the static field that "points" to the userExprFun
// that evaluates the where clause.
// arg 5
acb.pushMethodReference(mb, userExprFun);
}
// arg 6
mb.push(getResultSetNumber());
addOuterJoinArguments(acb, mb);
// Does right side return a single row
oneRowRightSide(acb, mb);
// estimated row count
mb.push(getCostEstimate().rowCount());
// estimated cost
mb.push(getCostEstimate().getEstimatedCost());
// run time statistics.
if (joinOrderStrategyProperties != null)
mb.push(PropertyUtil.sortProperties(joinOrderStrategyProperties));
else
mb.pushNull("java.lang.String");
return numArgs;
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class MatchingClauseNode method generateInsertUpdateRow.
/**
* <p>
* Generate a method to build a row for the temporary table for INSERT/UPDATE actions.
* The method stuffs each column in the row with the result of the corresponding
* expression built out of columns in the current row of the driving left join.
* The method returns the stuffed row.
* </p>
*/
private void generateInsertUpdateRow(ActivationClassBuilder acb, ResultColumnList selectList, ResultSetNode generatedScan, HalfOuterJoinNode hojn) throws StandardException {
// point expressions in the temporary row at the columns in the
// result column list of the driving left join.
adjustThenColumns(selectList, generatedScan, hojn);
_rowMakingMethodName = "mergeRowMakingMethod_" + _clauseNumber;
MethodBuilder mb = acb.getClassBuilder().newMethodBuilder(Modifier.PUBLIC, ClassName.ExecRow, _rowMakingMethodName);
mb.addThrownException(ClassName.StandardException);
_thenColumns.generateEvaluatedRow(acb, mb, false, true);
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class MatchingClauseNode method makeConstantAction.
// /////////////////////////////////////////////////////////////////////////////////
//
// generate() BEHAVIOR
//
// /////////////////////////////////////////////////////////////////////////////////
ConstantAction makeConstantAction(ActivationClassBuilder acb) throws StandardException {
// generate the clause-specific refinement
String refinementName = null;
if (_matchingRefinement != null) {
MethodBuilder userExprFun = acb.newUserExprFun();
_matchingRefinement.generateExpression(acb, userExprFun);
userExprFun.methodReturn();
// we are done modifying userExprFun, complete it.
userExprFun.complete();
refinementName = userExprFun.getName();
}
return getGenericConstantActionFactory().getMatchingClauseConstantAction(getClauseType(), refinementName, buildThenColumnSignature(), _rowMakingMethodName, _resultSetFieldName, _actionMethodName, _dml.makeConstantAction());
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class OperatorNode method pushSqlXmlUtil.
/**
* <p>
* Generate code that pushes an SqlXmlUtil instance onto the stack. The
* instance will be created and cached in the activation's constructor, so
* that we don't need to create a new instance for every row.
* </p>
*
* <p>
* If the {@code xmlQuery} parameter is non-null, there will also be code
* that compiles the query when the SqlXmlUtil instance is created.
* </p>
*
* @param acb builder for the class in which the generated code lives
* @param mb builder for the method that implements this operator
* @param xmlQuery the XML query to be executed by the operator, or
* {@code null} if this isn't an XMLEXISTS or XMLQUERY operator
* @param xmlOpName the name of the operator (ignored if {@code xmlQuery}
* is {@code null})
*/
static void pushSqlXmlUtil(ExpressionClassBuilder acb, MethodBuilder mb, String xmlQuery, String xmlOpName) {
// Create a field in which the instance can be cached.
LocalField sqlXmlUtil = acb.newFieldDeclaration(Modifier.PRIVATE | Modifier.FINAL, SqlXmlUtil.class.getName());
// Add code that creates the SqlXmlUtil instance in the constructor.
MethodBuilder constructor = acb.getConstructor();
constructor.pushNewStart(SqlXmlUtil.class.getName());
constructor.pushNewComplete(0);
constructor.putField(sqlXmlUtil);
// Compile the query, if one is specified.
if (xmlQuery == null) {
// No query. The SqlXmlUtil instance is still on the stack. Pop it
// to restore the initial state of the stack.
constructor.pop();
} else {
// Compile the query. This will consume the SqlXmlUtil instance
// and leave the stack in its initial state.
constructor.push(xmlQuery);
constructor.push(xmlOpName);
constructor.callMethod(VMOpcode.INVOKEVIRTUAL, SqlXmlUtil.class.getName(), "compileXQExpr", "void", 2);
}
// Read the cached value and push it onto the stack in the method
// generated for the operator.
mb.getField(sqlXmlUtil);
}
Aggregations