use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class ActivationClassBuilder method getCurrentSetup.
// /////////////////////////////////////////////////////////////////////
//
// CURRENT DATE/TIME SUPPORT
//
// /////////////////////////////////////////////////////////////////////
/*
The first time a current datetime is needed, create the class
level support for it. The first half of the logic is in our parent
class.
*/
@Override
protected LocalField getCurrentSetup() {
if (cdtField != null)
return cdtField;
LocalField lf = super.getCurrentSetup();
// 3) the execute method gets a statement (prior to the return)
// to tell cdt to restart:
// cdt.forget();
MethodBuilder execute = getExecuteMethod();
execute.getField(lf);
execute.callMethod(VMOpcode.INVOKEVIRTUAL, (String) null, "forget", "void", 0);
return lf;
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class PredicateList method generateStartKey.
/**
* @see OptimizablePredicateList#generateStartKey
*
* @exception StandardException Thrown on error
*/
public void generateStartKey(ExpressionClassBuilderInterface acbi, MethodBuilder mb, Optimizable optTable) throws StandardException {
ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi;
if (numberOfStartPredicates != 0) {
/* This sets up the method and the static field */
MethodBuilder exprFun = acb.newExprFun();
/* Now we fill in the body of the method */
LocalField rowField = generateIndexableRow(acb, numberOfStartPredicates);
int colNum = 0;
for (Predicate pred : this) {
if (!pred.isStartKey())
continue;
generateSetColumn(acb, exprFun, colNum, pred, optTable, rowField, true);
colNum++;
}
if (SanityManager.DEBUG) {
SanityManager.ASSERT(colNum == numberOfStartPredicates, "Number of start predicates does not match");
}
finishKey(acb, mb, exprFun, rowField);
return;
}
mb.pushNull(ClassName.GeneratedMethod);
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class PredicateList method generateSetColumn.
/**
* Generate the code to set the value from a predicate in an index column.
*
* @param acb The ActivationClassBuilder for the class we're building
* @param exprFun The MethodBuilder for the method we're building
* @param columnNumber The position number of the column we're setting
* the value in (zero-based)
* @param pred The Predicate with the value to put in the index column
* @param optTable The Optimizable table the column is in
* @param rowField The field that holds the indexable row
* @param isStartKey Are we generating start or stop key? This information
* is useful for "in"'s dynamic start/stop key, bug 3858
*
* @exception StandardException Thrown on error
*/
private void generateSetColumn(ExpressionClassBuilder acb, MethodBuilder exprFun, int columnNumber, Predicate pred, Optimizable optTable, LocalField rowField, boolean isStartKey) throws StandardException {
MethodBuilder mb;
/* Code gets generated in constructor if comparison against
* a constant, otherwise gets generated in the current
* statement block.
*/
boolean withKnownConstant = false;
if (pred.compareWithKnownConstant(optTable, false)) {
withKnownConstant = true;
mb = acb.getConstructor();
} else {
mb = exprFun;
}
int[] baseColumns = optTable.getTrulyTheBestAccessPath().getConglomerateDescriptor().getIndexDescriptor().baseColumnPositions();
boolean[] isAscending = optTable.getTrulyTheBestAccessPath().getConglomerateDescriptor().getIndexDescriptor().isAscending();
/* If the predicate is an IN-list probe predicate then we are
* using it as a start/stop key "placeholder", to be over-ridden
* at execution time. Put differently, we want to generate
* "column = ?" as a start/stop key and then use the "?" value
* as a placeholder into which we'll plug the various IN values
* at execution time.
*
* In that case "isIn" will be false here, which is fine: there's
* no need to generate dynamic start/stop keys like we do for
* "normal" IN lists because we're just using the key as a place-
* holder. So by generating the probe predicate ("column = ?")
* as a normal one-sided start/stop key, we get our requisite
* execution-time placeholder and that's that. For more on how
* we use this "placeholder", see MultiProbeTableScanResultSet.
*
* Note that we generate the corresponding IN-list values
* separately (see generateInListValues() in this class).
*/
boolean isIn = pred.getAndNode().getLeftOperand() instanceof InListOperatorNode;
/*
** Generate statements of the form
**
** r.setColumn(columnNumber, columnExpression);
**
** and put the generated statement in the allocator function.
*/
mb.getField(rowField);
mb.push(columnNumber + 1);
// second arg
if (isIn) {
pred.getSourceInList().generateStartStopKey(isAscending[columnNumber], isStartKey, acb, mb);
} else
pred.generateExpressionOperand(optTable, baseColumns[columnNumber], acb, mb);
mb.upCast(ClassName.DataValueDescriptor);
mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.Row, "setColumn", "void", 2);
/* Also tell the row if this column uses ordered null semantics */
if (!isIn) {
RelationalOperator relop = pred.getRelop();
boolean setOrderedNulls = relop.orderedNulls();
/* beetle 4464, performance work. If index column is not nullable
* (which is frequent), we should treat it as though nulls are
* ordered (indeed because they don't exist) so that we do not have
* to check null at scan time for each row, each column. This is
* an overload to "is null" operator, so that we have less overhead,
* provided that they don't interfere. It doesn't interfere if it
* doesn't overload if key is null. If key is null, but operator
* is not orderedNull type (is null), skipScan will use this flag
* (false) to skip scan.
*/
if ((!setOrderedNulls) && !relop.getColumnOperand(optTable).getTypeServices().isNullable()) {
if (withKnownConstant)
setOrderedNulls = true;
else {
ValueNode keyExp = relop.getExpressionOperand(optTable.getTableNumber(), baseColumns[columnNumber], (FromTable) optTable);
if (keyExp instanceof ColumnReference)
setOrderedNulls = !((ColumnReference) keyExp).getTypeServices().isNullable();
}
}
if (setOrderedNulls) {
mb.getField(rowField);
mb.push(columnNumber);
mb.callMethod(VMOpcode.INVOKEINTERFACE, ClassName.ExecIndexRow, "orderedNulls", "void", 1);
}
}
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class PredicateList method generateStopKey.
/**
* @see OptimizablePredicateList#generateStopKey
*
* @exception StandardException Thrown on error
*/
public void generateStopKey(ExpressionClassBuilderInterface acbi, MethodBuilder mb, Optimizable optTable) throws StandardException {
ExpressionClassBuilder acb = (ExpressionClassBuilder) acbi;
if (numberOfStopPredicates != 0) {
/* This sets up the method and the static field */
MethodBuilder exprFun = acb.newExprFun();
/* Now we fill in the body of the method */
LocalField rowField = generateIndexableRow(acb, numberOfStopPredicates);
int colNum = 0;
for (Predicate pred : this) {
if (!pred.isStopKey())
continue;
generateSetColumn(acb, exprFun, colNum, pred, optTable, rowField, false);
colNum++;
}
if (SanityManager.DEBUG) {
SanityManager.ASSERT(colNum == numberOfStopPredicates, "Number of stop predicates does not match");
}
finishKey(acb, mb, exprFun, rowField);
return;
}
mb.pushNull(ClassName.GeneratedMethod);
}
use of org.apache.derby.iapi.services.compiler.MethodBuilder in project derby by apache.
the class HashTableNode method generateMinion.
/**
* Logic shared by generate() and generateResultSet().
*
* @param acb The ExpressionClassBuilder for the class being built
* @param mb the method the expression will go into
*
* @exception StandardException Thrown on error
*/
private void generateMinion(ExpressionClassBuilder acb, MethodBuilder mb, boolean genChildResultSet) throws StandardException {
MethodBuilder userExprFun;
ValueNode searchClause = null;
ValueNode equijoinClause = null;
/* The tableProperties, if non-null, must be correct to get this far.
* We simply call verifyProperties to set initialCapacity and
* loadFactor.
*/
verifyProperties(getDataDictionary());
/* Put the predicates back into the tree */
if (searchPredicateList != null) {
// Remove any redundant predicates before restoring
searchPredicateList.removeRedundantPredicates();
searchClause = searchPredicateList.restorePredicates();
/* Allow the searchPredicateList to get garbage collected now
* that we're done with it.
*/
searchPredicateList = null;
}
// for the single table predicates, we generate an exprFun
// that evaluates the expression of the clause
// against the current row of the child's result.
// if the restriction is empty, simply pass null
// to optimize for run time performance.
// generate the function and initializer:
// Note: Boolean lets us return nulls (boolean would not)
// private Boolean exprN()
// {
// return <<searchClause.generate(ps)>>;
// }
// static Method exprN = method pointer to exprN;
// Map the result columns to the source columns
ResultColumnList.ColumnMapping mappingArrays = getResultColumns().mapSourceColumns();
int[] mapArray = mappingArrays.mapArray;
int mapArrayItem = acb.addItem(new ReferencedColumnsDescriptorImpl(mapArray));
// Save the hash key columns
FormatableIntHolder[] fihArray = FormatableIntHolder.getFormatableIntHolders(hashKeyColumns());
FormatableArrayHolder hashKeyHolder = new FormatableArrayHolder(fihArray);
int hashKeyItem = acb.addItem(hashKeyHolder);
/* Generate the HashTableResultSet:
* arg1: childExpress - Expression for childResultSet
* arg2: searchExpress - Expression for single table predicates
* arg3 : equijoinExpress - Qualifier[] for hash table look up
* arg4: projectExpress - Expression for projection, if any
* arg5: resultSetNumber
* arg6: mapArrayItem - item # for mapping of source columns
* arg7: reuseResult - whether or not the result row can be reused
* (ie, will it always be the same)
* arg8: hashKeyItem - item # for int[] of hash column #s
* arg9: removeDuplicates - don't remove duplicates in hash table (for now)
* arg10: maxInMemoryRowCount - max row size for in-memory hash table
* arg11: initialCapacity - initialCapacity for java.util.Hashtable
* arg12 : loadFactor - loadFactor for java.util.Hashtable
* arg13: estimated row count
* arg14: estimated cost
* arg15: close method
*/
acb.pushGetResultSetFactoryExpression(mb);
if (genChildResultSet)
childResult.generateResultSet(acb, mb);
else
childResult.generate((ActivationClassBuilder) acb, mb);
/* Get the next ResultSet #, so that we can number this ResultSetNode, its
* ResultColumnList and ResultSet.
*/
assignResultSetNumber();
/* Set the point of attachment in all subqueries attached
* to this node.
*/
if (pSubqueryList != null && pSubqueryList.size() > 0) {
pSubqueryList.setPointOfAttachment(getResultSetNumber());
if (SanityManager.DEBUG) {
SanityManager.ASSERT(pSubqueryList.size() == 0, "pSubqueryList.size() expected to be 0");
}
}
if (rSubqueryList != null && rSubqueryList.size() > 0) {
rSubqueryList.setPointOfAttachment(getResultSetNumber());
if (SanityManager.DEBUG) {
SanityManager.ASSERT(rSubqueryList.size() == 0, "rSubqueryList.size() expected to be 0");
}
}
// Get the final cost estimate based on child's cost.
setCostEstimate(childResult.getFinalCostEstimate());
// if there is no searchClause, we just want to pass null.
if (searchClause == null) {
mb.pushNull(ClassName.GeneratedMethod);
} else {
// this sets up the method and the static field.
// generates:
// DataValueDescriptor userExprFun { }
userExprFun = acb.newUserExprFun();
// searchClause knows it is returning its value;
/* generates:
* return <searchClause.generate(acb)>;
* and adds it to userExprFun
* NOTE: The explicit cast to DataValueDescriptor is required
* since the searchClause may simply be a boolean column or subquery
* which returns a boolean. For example:
* where booleanColumn
*/
searchClause.generateExpression(acb, userExprFun);
userExprFun.methodReturn();
/* PUSHCOMPILER
userSB.newReturnStatement(searchClause.generateExpression(acb, userSB));
*/
// we are done modifying userExprFun, complete it.
userExprFun.complete();
// searchClause 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.
acb.pushMethodReference(mb, userExprFun);
}
/* Generate the qualifiers for the look up into
* the hash table.
*/
joinPredicateList.generateQualifiers(acb, mb, (Optimizable) childResult, false);
/* Determine whether or not reflection is needed for the projection.
* Reflection is not needed if all of the columns map directly to source
* columns.
*/
if (reflectionNeededForProjection()) {
// for the resultColumns, we generate a userExprFun
// that creates a new row from expressions against
// the current row of the child's result.
// (Generate optimization: see if we can simply
// return the current row -- we could, but don't, optimize
// the function call out and have execution understand
// that a null function pointer means take the current row
// as-is, with the performance trade-off as discussed above.)
/* Generate the Row function for the projection */
getResultColumns().generateCore(acb, mb, false);
} else {
mb.pushNull(ClassName.GeneratedMethod);
}
mb.push(getResultSetNumber());
mb.push(mapArrayItem);
mb.push(getResultColumns().reusableResult());
mb.push(hashKeyItem);
mb.push(false);
mb.push(-1L);
mb.push(initialCapacity);
mb.push(loadFactor);
mb.push(getCostEstimate().singleScanRowCount());
mb.push(getCostEstimate().getEstimatedCost());
mb.callMethod(VMOpcode.INVOKEINTERFACE, (String) null, "getHashTableResultSet", ClassName.NoPutResultSet, 14);
}
Aggregations