📄 projectrestrictnode.java
字号:
/** * Return the user specified join strategy, if any for this table. * * @return The user specified join strategy, if any for this table. */ String getUserSpecifiedJoinStrategy() { if (childResult instanceof FromTable) { return ((FromTable) childResult).getUserSpecifiedJoinStrategy(); } else { return userSpecifiedJoinStrategy; } } /** * Prints the sub-nodes of this object. See QueryTreeNode.java for * how tree printing is supposed to work. * * @param depth The depth of this node in the tree * * @return Nothing */ public void printSubNodes(int depth) { if (SanityManager.DEBUG) { super.printSubNodes(depth); if (restriction != null) { printLabel(depth, "restriction: "); restriction.treePrint(depth + 1); } if (restrictionList != null) { printLabel(depth, "restrictionList: "); restrictionList.treePrint(depth + 1); } if (projectSubquerys != null) { printLabel(depth, "projectSubquerys: "); projectSubquerys.treePrint(depth + 1); } if (restrictSubquerys != null) { printLabel(depth, "restrictSubquerys: "); restrictSubquerys.treePrint(depth + 1); } } } /** * Put a ProjectRestrictNode on top of each FromTable in the FromList. * ColumnReferences must continue to point to the same ResultColumn, so * that ResultColumn must percolate up to the new PRN. However, * that ResultColumn will point to a new expression, a VirtualColumnNode, * which points to the FromTable and the ResultColumn that is the source for * the ColumnReference. * (The new PRN will have the original of the ResultColumnList and * the ResultColumns from that list. The FromTable will get shallow copies * of the ResultColumnList and its ResultColumns. ResultColumn.expression * will remain at the FromTable, with the PRN getting a new * VirtualColumnNode for each ResultColumn.expression.) * We then project out the non-referenced columns. If there are no referenced * columns, then the PRN's ResultColumnList will consist of a single ResultColumn * whose expression is 1. * * @param numTables Number of tables in the DML Statement * @param gbl The group by list, if any * @param fromList The from list, if any * * @return The generated ProjectRestrictNode atop the original FromTable. * * @exception StandardException Thrown on error */ public ResultSetNode preprocess(int numTables, GroupByList gbl, FromList fromList) throws StandardException { childResult = childResult.preprocess(numTables, gbl, fromList); /* Build the referenced table map */ referencedTableMap = (JBitSet) childResult.getReferencedTableMap().clone(); return this; } /** * Push expressions down to the first ResultSetNode which can do expression * evaluation and has the same referenced table map. * RESOLVE - This means only pushing down single table expressions to * ProjectRestrictNodes today. Once we have a better understanding of how * the optimizer will work, we can push down join clauses. * * @param predicateList The PredicateList. * * @exception StandardException Thrown on error */ public void pushExpressions(PredicateList predicateList) throws StandardException { PredicateList pushPList = null; if (SanityManager.DEBUG) SanityManager.ASSERT(predicateList != null, "predicateList is expected to be non-null"); /* Push single table predicates down to the left of an outer * join, if possible. (We need to be able to walk an entire * join tree.) */ if (childResult instanceof JoinNode) { ((FromTable) childResult).pushExpressions(predicateList); } /* Build a list of the single table predicates that we can push down */ pushPList = predicateList.getPushablePredicates(referencedTableMap); /* If this is a PRN above a SelectNode, probably due to a * view or derived table which couldn't be flattened, then see * if we can push any of the predicates which just got pushed * down to our level into the SelectNode. */ if (pushPList != null && (childResult instanceof SelectNode)) { pushPList.pushExpressionsIntoSelect((SelectNode) childResult, false); } /* DERBY-649: Push simple predicates into Unions. It would be up to UnionNode * to decide if these predicates can be pushed further into underlying SelectNodes * or UnionNodes. Note, we also keep the predicateList at this * ProjectRestrictNode in case the predicates are not pushable or only * partially pushable. * * It is possible to expand this optimization in UnionNode later. */ if (pushPList != null && (childResult instanceof UnionNode)) ((UnionNode)childResult).pushExpressions(pushPList); if (restrictionList == null) { restrictionList = pushPList; } else if (pushPList != null && pushPList.size() != 0) { /* Concatenate the 2 PredicateLists */ restrictionList.destructiveAppend(pushPList); } /* RESOLVE - this looks like the place to try to try to push the * predicates through the ProjectRestrict. Seems like we should * "rebind" the column references and reset the referenced table maps * in restrictionList and then call childResult.pushExpressions() on * restrictionList. */ } /** * Add a new predicate to the list. This is useful when doing subquery * transformations, when we build a new predicate with the left side of * the subquery operator and the subquery's result column. * * @param predicate The predicate to add * * @return ResultSetNode The new top of the tree. * * @exception StandardException Thrown on error */ public ResultSetNode addNewPredicate(Predicate predicate) throws StandardException { if (restrictionList == null) { restrictionList = (PredicateList) getNodeFactory().getNode( C_NodeTypes.PREDICATE_LIST, getContextManager()); } restrictionList.addPredicate(predicate); return this; } /** * Evaluate whether or not the subquery in a FromSubquery is flattenable. * Currently, a FSqry is flattenable if all of the following are true: * o Subquery is a SelectNode. * o It contains no top level subqueries. (RESOLVE - we can relax this) * o It does not contain a group by or having clause * o It does not contain aggregates. * * @param fromList The outer from list * * @return boolean Whether or not the FromSubquery is flattenable. */ public boolean flattenableInFromSubquery(FromList fromList) { /* Flattening currently involves merging predicates and FromLists. * We don't have a FromList, so we can't flatten for now. */ /* RESOLVE - this will introduce yet another unnecessary PRN */ return false; } /** * Ensure that the top of the RSN tree has a PredicateList. * * @param numTables The number of tables in the query. * @return ResultSetNode A RSN tree with a node which has a PredicateList on top. * * @exception StandardException Thrown on error */ public ResultSetNode ensurePredicateList(int numTables) throws StandardException { return this; } /** * Optimize this ProjectRestrictNode. * * @param dataDictionary The DataDictionary to use for optimization * @param predicateList The PredicateList to optimize. This should * be a join predicate. * @param outerRows The number of outer joining rows * * @return ResultSetNode The top of the optimized subtree * * @exception StandardException Thrown on error */ public ResultSetNode optimize(DataDictionary dataDictionary, PredicateList predicates, double outerRows) throws StandardException { /* We need to implement this method since a PRN can appear above a * SelectNode in a query tree. */ childResult = childResult.optimize(dataDictionary, restrictionList, outerRows); Optimizer optimizer = getOptimizer( (FromList) getNodeFactory().getNode( C_NodeTypes.FROM_LIST, getNodeFactory().doJoinOrderOptimization(), this, getContextManager()), predicates, dataDictionary, (RequiredRowOrdering) null); // RESOLVE: SHOULD FACTOR IN THE NON-OPTIMIZABLE PREDICATES THAT // WERE NOT PUSHED DOWN costEstimate = optimizer.newCostEstimate(); costEstimate.setCost(childResult.getCostEstimate().getEstimatedCost(), childResult.getCostEstimate().rowCount(), childResult.getCostEstimate().singleScanRowCount()); return this; } /** * Get the CostEstimate for this ProjectRestrictNode. * * @return The CostEstimate for this ProjectRestrictNode, which is * the cost estimate for the child node. */ public CostEstimate getCostEstimate() { /* ** The cost estimate will be set here if either optimize() or ** optimizeIt() was called on this node. It's also possible ** that optimization was done directly on the child node, ** in which case the cost estimate will be null here. */ if (costEstimate == null) return childResult.getCostEstimate(); else { return costEstimate; } } /** * Get the final CostEstimate for this ProjectRestrictNode. * * @return The final CostEstimate for this ProjectRestrictNode, which is * the final cost estimate for the child node. */ public CostEstimate getFinalCostEstimate() throws StandardException { if (finalCostEstimate != null) // we already set it, so just return it. return finalCostEstimate; // If the child result set is an Optimizable, then this node's // final cost is that of the child. Otherwise, this node must // hold "trulyTheBestAccessPath" for it's child so we pull // the final cost from there. if (childResult instanceof Optimizable) finalCostEstimate = childResult.getFinalCostEstimate(); else finalCostEstimate = getTrulyTheBestAccessPath().getCostEstimate(); return finalCostEstimate; } /** * For joins, the tree will be (nodes are left out if the clauses * are empty): * * ProjectRestrictResultSet -- for the having and the select list * SortResultSet -- for the group by list * ProjectRestrictResultSet -- for the where and the select list (if no group or having) * the result set for the fromList * * * @exception StandardException Thrown on error */ public void generate(ActivationClassBuilder acb, MethodBuilder mb) throws StandardException { if (SanityManager.DEBUG) SanityManager.ASSERT(resultColumns != null, "Tree structure bad"); generateMinion( acb, mb, false); } /** * General logic shared by Core compilation. * * @param ecb The ExpressionClassBuilder for the class being built * @param mb The method the expression will go into * * * @exception StandardException Thrown on error */ public void generateResultSet(ExpressionClassBuilder acb, MethodBuilder mb) throws StandardException { generateMinion( acb, mb, true); } /** * Logic shared by generate() and generateResultSet(). * * @param ecb The ExpressionClassBuilder for the class being built * @param mb The method the expression will go into * * @return The compiled Expression * * @exception StandardException Thrown on error */ private void generateMinion(ExpressionClassBuilder acb, MethodBuilder mb, boolean genChildResultSet) throws StandardException { /* If this ProjectRestrict doesn't do anything, bypass its generation. * (Remove any true and true predicates first, as they could be left * by the like transformation.) */ if (restrictionList != null && restrictionList.size() > 0) { restrictionList.eliminateBooleanTrueAndBooleanTrue(); } if (nopProjectRestrict()) { generateNOPProjectRestrict(); if (genChildResultSet) childResult.generateResultSet(acb, mb); else childResult.generate((ActivationClassBuilder)acb, mb); costEstimate = childResult.getFinalCostEstimate(); return; } // build up the tree. /* Put the predicates back into the tree */ if (restrictionList != null) { constantRestriction = restrictionList.restoreConstantPredicates(); // Remove any redundant predicates before restoring restrictionList.removeRedundantPredicates(); restriction = restrictionList.restorePredicates(); /* Allow the restrictionList to get garbage collected now * that we're done with it. */ restrictionList = null; } // for the restriction, 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 <<restriction.generate(ps)>>; // } // static Method exprN = method pointer to exprN; // Map the result columns to the source columns int[] mapArray = resultColumns.mapSourceColumns(); int mapArrayItem = acb.addItem(new ReferencedColumnsDescriptorImpl(mapArray)); /* Will this node do a projection? */ boolean doesProjection = true; /* Does a projection unless same # of columns in same order * as child. */ if ( (! reflectionNeededForProjection()) && mapArray != null && mapArray.length == childResult.getResultColumns().size()) { /* mapArray entries are 1-based */ int index = 0; for ( ; index < mapArray.length; index++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -