use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class ExpressionClassBuilder method beginConstructor.
// /////////////////////////////////////////////////////////////////////
//
// CONSTRUCTOR MANAGEMENT
//
// /////////////////////////////////////////////////////////////////////
private void beginConstructor() {
// create a constructor that just calls super.
MethodBuilder realConstructor = cb.newConstructorBuilder(Modifier.PUBLIC);
realConstructor.callSuper();
realConstructor.methodReturn();
realConstructor.complete();
constructor = cb.newMethodBuilder(Modifier.PUBLIC, "void", "postConstructor");
constructor.addThrownException(ClassName.StandardException);
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class StatementNode method generate.
/**
* Do code generation for this statement.
*
* @param byteCode the generated byte code for this statement.
* if non-null, then the byte code is saved
* here.
*
* @return A GeneratedClass for this statement
*
* @exception StandardException Thrown on error
*/
public GeneratedClass generate(ByteArray byteCode) throws StandardException {
// start the new activation class.
// it starts with the Execute method
// and the appropriate superclass (based on
// statement type, from inspecting the queryTree).
int nodeChoice = activationKind();
/* RESOLVE: Activation hierarchy was way too complicated
* and added no value. Simple thing to do was to simply
* leave calling code alone and to handle here and to
* eliminate unnecessary classes.
*/
String superClass;
switch(nodeChoice) {
case NEED_CURSOR_ACTIVATION:
superClass = ClassName.CursorActivation;
break;
case NEED_DDL_ACTIVATION:
return getClassFactory().loadGeneratedClass("org.apache.derby.impl.sql.execute.ConstantActionActivation", null);
case NEED_NOTHING_ACTIVATION:
case NEED_ROW_ACTIVATION:
case NEED_PARAM_ACTIVATION:
superClass = ClassName.BaseActivation;
break;
default:
throw StandardException.newException(SQLState.LANG_UNAVAILABLE_ACTIVATION_NEED, String.valueOf(nodeChoice));
}
ActivationClassBuilder generatingClass = new ActivationClassBuilder(superClass, getCompilerContext());
// Create the method that generates the ResultSet tree used when
// executing this statement. Implements the abstract method
// BaseActivation.createResultSet().
MethodBuilder mbWorker = generatingClass.getClassBuilder().newMethodBuilder(Modifier.PROTECTED, ClassName.ResultSet, "createResultSet");
mbWorker.addThrownException(ClassName.StandardException);
// Generate the complete ResultSet tree for this statement.
// This step may add statements into the execute method
// for per-execution actions.
generate(generatingClass, mbWorker);
mbWorker.methodReturn();
mbWorker.complete();
// wrap up the activation class definition
// generate on the tree gave us back the newExpr
// for getting a result set on the tree.
// we put it in a return statement and stuff
// it in the execute method of the activation.
// The generated statement is the expression:
// the activation class builder takes care of constructing it
// for us, given the resultSetExpr to use.
// return (this.resultSet = #resultSetExpr);
generatingClass.finishExecuteMethod();
// wrap up the constructor by putting a return at the end of it
generatingClass.finishConstructor();
try {
// cook the completed class into a real class
// and stuff it into activationClass
GeneratedClass activationClass = generatingClass.getGeneratedClass(byteCode);
return activationClass;
} catch (StandardException e) {
String msgId = e.getMessageId();
if (SQLState.GENERATED_CLASS_LIMIT_EXCEEDED.equals(msgId) || SQLState.GENERATED_CLASS_LINKAGE_ERROR.equals(msgId)) {
throw StandardException.newException(SQLState.LANG_QUERY_TOO_COMPLEX, e);
}
throw e;
}
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class SubqueryNode method generateMaterialization.
/*
** Materialize the subquery in question. Given the expression
** that represents the subquery, this returns fieldX where
** fieldX is set up as follows:
**
** private ... fieldX
**
** execute()
** {
** fieldX = <subqueryExpression>
** ...
** }
**
** So we wind up evaluating the subquery when we start
** execution. Obviously, it is absolutely necessary that
** the subquery is invariant and has no correlations
** for this to work.
**
** Ideally we wouldn't evaluate the expression subquery
** until we know we need to, but because we are marking
** this expression subquery as pushable, we must evaluate
** it up front because it might wind up as a qualification,
** and we cannot execute a subquery in the store as a
** qualification because the store executes qualifications
** while holding a latch.
**
** @param acb
** @param type
** @param subqueryExpression
*/
private LocalField generateMaterialization(ActivationClassBuilder acb, MethodBuilder mbsq, String type) {
MethodBuilder mb = acb.getExecuteMethod();
// declare field
LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, type);
/* Generate the call to the new method */
mb.pushThis();
mb.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, mbsq.getName(), type, 0);
// generate: field = value (value is on stack)
mb.setField(field);
return field;
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class PredicateList method generateIndexableRow.
/**
* Generate the indexable row for a start key or stop key.
*
* @param acb The ActivationClassBuilder for the class we're building
* @param numberOfColumns The number of columns in the key
*
* @return The field that holds the indexable row
*/
private LocalField generateIndexableRow(ExpressionClassBuilder acb, int numberOfColumns) {
MethodBuilder mb = acb.getConstructor();
/*
** Generate a call to get an indexable row
** with the given number of columns
*/
// instance
acb.pushGetExecutionFactoryExpression(mb);
mb.push(numberOfColumns);
mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ExecutionFactory, "getIndexableRow", ClassName.ExecIndexRow, 1);
/*
** Assign the indexable row to a field, and put this assignment into
** the constructor for the activation class. This way, we only have
** to get the row once.
*/
LocalField field = acb.newFieldDeclaration(Modifier.PRIVATE, ClassName.ExecIndexRow);
mb.setField(field);
return field;
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class PredicateList method generateQualifiers.
/**
* @see OptimizablePredicateList#generateQualifiers
*
* @exception StandardException Thrown on error
*/
public void generateQualifiers(ExpressionClassBuilderInterface acbi, MethodBuilder mb, Optimizable optTable, boolean absolute) throws StandardException {
String retvalType = ClassName.Qualifier + "[][]";
// If there are no qualifiers, return null.
if (numberOfQualifiers == 0) {
mb.pushNull(retvalType);
return;
}
ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi;
MethodBuilder consMB = acb.getConstructor();
MethodBuilder executeMB = acb.getExecuteMethod();
/* Create and initialize the array of Qualifiers */
LocalField qualField = acb.newFieldDeclaration(Modifier.PRIVATE, retvalType);
/*
** Stick a reinitialize of the Qualifier array in execute().
** Done because although we call Exec/Qualifier.clearOrderableCache()
** before each query, we only clear the cache for VARIANT and
** SCAN_INVARIANT qualifiers. However, each time the same
** statement is executed, even the QUERY_INVARIANT qualifiers
** need to be flushed. For example:
** prepare select c1 from t where c1 = (select max(c1) from t) as p;
** execute p; -- we now have the materialized subquery result (1)
** -- in our predicate
** insert into t values 666;
** execute p; -- we need to clear out 1 and recache the subq result
*/
// PUSHCOMPILER
// if (mb == executeMB) {
// System.out.println("adding code to method in two places");
// new Throwable().printStackTrace();
// }
//
// generate code to reinitializeQualifiers(Qualifier[][] qualifiers)
// first arg to reinitializeQualifiers()
executeMB.getField(qualField);
executeMB.callMethod(VMOpcode.INVOKESTATIC, acb.getBaseClassName(), "reinitializeQualifiers", "void", 1);
if (SanityManager.DEBUG) {
if (numberOfQualifiers > size()) {
SanityManager.THROWASSERT("numberOfQualifiers(" + numberOfQualifiers + ") > size(" + size() + ")." + ":" + this.hashCode());
}
}
// Determine number of leading AND qualifiers, and subsequent
// trailing OR qualifiers.
int num_of_or_conjunctions = 0;
for (int i = 0; i < numberOfQualifiers; i++) {
if (elementAt(i).isOrList()) {
num_of_or_conjunctions++;
}
}
/* Assign the initializer to the Qualifier[] field */
consMB.pushNewArray(ClassName.Qualifier + "[]", num_of_or_conjunctions + 1);
consMB.setField(qualField);
// Allocate qualifiers[0] which is an entry for each of the leading
// AND clauses.
// 1st arg allocateQualArray
consMB.getField(qualField);
// 2nd arg allocateQualArray
consMB.push(0);
// 3rd arg allocateQualArray
consMB.push(numberOfQualifiers - num_of_or_conjunctions);
consMB.callMethod(VMOpcode.INVOKESTATIC, acb.getBaseClassName(), "allocateQualArray", "void", 3);
/* Sort the qualifiers by "selectivity" before generating.
* We want the qualifiers ordered by selectivity with the
* most selective ones first. There are 3 groups of qualifiers:
* = and IS NULL are the most selective,
* <> and IS NOT NULL are the least selective and
* all of the other RELOPs are in between.
* We break the list into 4 parts (3 types of qualifiers and
* then everything else) and then rebuild the ordered list.
* RESOLVE - we will eventually want to order the qualifiers
* by (column #, selectivity) once the store does just in time
* instantiation.
*/
orderQualifiers();
/* Generate each of the qualifiers, if any */
// First generate the "leading" AND qualifiers.
int qualNum = 0;
int size = size();
boolean gotOrQualifier = false;
for (int index = 0; index < size; index++) {
Predicate pred = elementAt(index);
if (!pred.isQualifier()) {
continue;
} else if (pred.isOrList()) {
gotOrQualifier = true;
// will generate the OR qualifiers below.
break;
} else {
generateSingleQualifierCode(consMB, optTable, absolute, acb, pred.getRelop(), qualField, 0, qualNum);
qualNum++;
}
}
if (gotOrQualifier) {
// process each set of or's into a list which are AND'd. Each
// predicate will become an array list in the qualifier array of
// array's.
//
// The first list of And's went into qual[0][0...N]
// Now each subquent predicate is actually a list of OR's so
// will be passed as:
// 1st OR predicate -> qual[1][0.. number of OR terms]
// 2nd OR predicate -> qual[2][0.. number of OR terms]
// ...
//
int and_idx = 1;
for (int index = qualNum; index < size; index++, and_idx++) {
Predicate pred = elementAt(index);
if (SanityManager.DEBUG) {
SanityManager.ASSERT(pred.isOrList());
}
// create an ArrayList of the OR nodes. We need the count
// of Or's in order to first generate the allocateQualArray()
// call, then we walk the list assigning each of the OR's to
// entries in the array in generateSingleQualifierCode().
ArrayList<RelationalOperator> a_list = new ArrayList<RelationalOperator>();
QueryTreeNode node = pred.getAndNode().getLeftOperand();
while (node instanceof OrNode) {
OrNode or_node = (OrNode) node;
// (ie. A = 1)
if (or_node.getLeftOperand() instanceof RelationalOperator) {
a_list.add((RelationalOperator) or_node.getLeftOperand());
}
// The next OR node in the list if linked to the right.
node = or_node.getRightOperand();
}
// Allocate an array to hold each of the terms of this OR,
// clause. ie. (a = 1 or b = 2), will allocate a 2 entry array.
// 1st arg allocateQualArray
consMB.getField(qualField);
// 2nd arg allocateQualArray
consMB.push(and_idx);
// 3rd arg allocateQualArray
consMB.push(a_list.size());
consMB.callMethod(VMOpcode.INVOKESTATIC, acb.getBaseClassName(), "allocateQualArray", "void", 3);
// finally transfer the nodes to the 2-d qualifier
for (int i = 0; i < a_list.size(); i++) {
generateSingleQualifierCode(consMB, optTable, absolute, acb, a_list.get(i), qualField, and_idx, i);
}
qualNum++;
}
}
if (SanityManager.DEBUG) {
SanityManager.ASSERT(qualNum == numberOfQualifiers, qualNum + " Qualifiers found, " + numberOfQualifiers + " expected.");
}
/*
** Return a reference to the field that holds the initialized
** array of Qualifiers.
*/
mb.getField(qualField);
}
Aggregations