📄 tableoperatornode.java
字号:
} /** * Bind the result columns of this ResultSetNode when there is no * base table to bind them to. This is useful for SELECT statements, * where the result columns get their types from the expressions that * live under them. * * @param fromListParam FromList to use/append to. * * @return Nothing * * @exception StandardException Thrown on error */ public void bindResultColumns(FromList fromListParam) throws StandardException { leftResultSet.bindResultColumns(fromListParam); rightResultSet.bindResultColumns(fromListParam); } /** * Bind the result columns for this ResultSetNode to a base table. * This is useful for INSERT and UPDATE statements, where the * result columns get their types from the table being updated or * inserted into. * If a result column list is specified, then the verification that the * result column list does not contain any duplicates will be done when * binding them by name. * * @param targetTableDescriptor The TableDescriptor for the table being * updated or inserted into * @param targetColumnList For INSERT statements, the user * does not have to supply column * names (for example, "insert into t * values (1,2,3)". When this * parameter is null, it means that * the user did not supply column * names, and so the binding should * be done based on order. When it * is not null, it means do the binding * by name, not position. * @param statement Calling DMLStatementNode (Insert or Update) * @param fromListParam FromList to use/append to. * * @return Nothing * * @exception StandardException Thrown on error */ public void bindResultColumns(TableDescriptor targetTableDescriptor, FromVTI targetVTI, ResultColumnList targetColumnList, DMLStatementNode statement, FromList fromListParam) throws StandardException { leftResultSet.bindResultColumns(targetTableDescriptor, targetVTI, targetColumnList, statement, fromListParam); rightResultSet.bindResultColumns(targetTableDescriptor, targetVTI, targetColumnList, statement, fromListParam); } /** * Determine whether or not the specified name is an exposed name in * the current query block. * * @param name The specified name to search for as an exposed name. * @param schemaName Schema name, if non-null. * @param exactMatch Whether or not we need an exact match on specified schema and table * names or match on table id. * * @return The FromTable, if any, with the exposed name. * * @exception StandardException Thrown on error */ protected FromTable getFromTableByName(String name, String schemaName, boolean exactMatch) throws StandardException { FromTable result = leftResultSet.getFromTableByName(name, schemaName, exactMatch); /* We search both sides for a TableOperatorNode (join nodes) * but only the left side for a UnionNode. */ if (result == null) { result = rightResultSet.getFromTableByName(name, schemaName, exactMatch); } return result; } /** * 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 { leftResultSet = leftResultSet.preprocess(numTables, gbl, fromList); /* If leftResultSet is a FromSubquery, then we must explicitly extract * out the subquery (flatten it). (SelectNodes have their own * method of flattening them. */ if (leftResultSet instanceof FromSubquery) { leftResultSet = ((FromSubquery) leftResultSet).extractSubquery(numTables); } rightResultSet = rightResultSet.preprocess(numTables, gbl, fromList); /* If rightResultSet is a FromSubquery, then we must explicitly extract * out the subquery (flatten it). (SelectNodes have their own * method of flattening them. */ if (rightResultSet instanceof FromSubquery) { rightResultSet = ((FromSubquery) rightResultSet).extractSubquery(numTables); } /* Build the referenced table map (left || right) */ referencedTableMap = (JBitSet) leftResultSet.getReferencedTableMap().clone(); referencedTableMap.or((JBitSet) rightResultSet.getReferencedTableMap()); referencedTableMap.set(tableNumber); /* Only generate a PRN if this node is not a flattenable join node. */ if (isFlattenableJoinNode()) { return this; } else { /* Project out any unreferenced RCs before we generate the PRN. * NOTE: We have to do this at the end of preprocess since it has to * be from the bottom up. We can't do it until the join expression is * bound, since the join expression may contain column references that * are not referenced anywhere else above us. */ projectResultColumns(); return genProjectRestrict(numTables); } } /** * Find the unreferenced result columns and project them out. This is used in pre-processing joins * that are not flattened into the where clause. */ void projectResultColumns() throws StandardException { resultColumns.doProjection(); } /** * Set the referenced columns in the column list if it may not be correct. */ void setReferencedColumns() {} /** * Optimize a TableOperatorNode. * * @param dataDictionary The DataDictionary to use for optimization * @param predicateList The PredicateList to apply. * * @return ResultSetNode The top of the optimized query tree * * @exception StandardException Thrown on error */ public ResultSetNode optimize(DataDictionary dataDictionary, PredicateList predicateList, double outerRows) throws StandardException { /* Get an optimizer, so we can get a cost structure */ Optimizer optimizer = getOptimizer( (FromList) getNodeFactory().getNode( C_NodeTypes.FROM_LIST, getNodeFactory().doJoinOrderOptimization(), this, getContextManager()), predicateList, dataDictionary, (RequiredRowOrdering) null); costEstimate = optimizer.newCostEstimate(); /* RESOLVE: This is just a stub for now */ leftResultSet = leftResultSet.optimize( dataDictionary, predicateList, outerRows); rightResultSet = rightResultSet.optimize( dataDictionary, predicateList, outerRows); /* The cost is the sum of the two child costs */ costEstimate.setCost(leftResultSet.getCostEstimate().getEstimatedCost(), leftResultSet.getCostEstimate().rowCount(), leftResultSet.getCostEstimate().singleScanRowCount() + rightResultSet.getCostEstimate().singleScanRowCount()); costEstimate.add(rightResultSet.costEstimate, costEstimate); return this; } /** * @see ResultSetNode#modifyAccessPaths * * @exception StandardException Thrown on error */ public ResultSetNode modifyAccessPaths() throws StandardException { /* Beetle 4454 - union all with another union all would modify access * paths twice causing NullPointerException, make sure we don't * do this again, if we have already done it in modifyAccessPaths(outertables) */ if (!leftModifyAccessPathsDone) { if (leftOptimizer != null) leftOptimizer.modifyAccessPaths(); else { // If this is a SetOperatorNode then we may have pushed // predicates down to the children. If that's the case // then we need to pass those predicates down as part // of the modifyAccessPaths call so that they can be // pushed one last time, in prep for generation. if (this instanceof SetOperatorNode) { SetOperatorNode setOp = (SetOperatorNode)this; leftResultSet = leftResultSet.modifyAccessPaths( setOp.getLeftOptPredicateList()); } else leftResultSet = leftResultSet.modifyAccessPaths(); } } if (!rightModifyAccessPathsDone) { if (rightOptimizer != null) rightOptimizer.modifyAccessPaths(); else { if (this instanceof SetOperatorNode) { SetOperatorNode setOp = (SetOperatorNode)this; rightResultSet = rightResultSet.modifyAccessPaths( setOp.getRightOptPredicateList()); } else rightResultSet = rightResultSet.modifyAccessPaths(); } } return this; } /** * Search to see if a query references the specifed table name. * * @param name Table name (String) to search for. * @param baseTable Whether or not name is for a base table * * @return true if found, else false * * @exception StandardException Thrown on error */ public boolean referencesTarget(String name, boolean baseTable) throws StandardException { return leftResultSet.referencesTarget(name, baseTable) || rightResultSet.referencesTarget(name, baseTable); } /** * Return true if the node references SESSION schema tables (temporary or permanent) * * @return true if references SESSION schema tables, else false * * @exception StandardException Thrown on error */ public boolean referencesSessionSchema() throws StandardException { return leftResultSet.referencesSessionSchema() || rightResultSet.referencesSessionSchema(); } /** * Optimize a source result set to this table operator. * * @exception StandardException Thrown on error */ protected ResultSetNode optimizeSource( Optimizer optimizer, ResultSetNode sourceResultSet, PredicateList predList, CostEstimate outerCost) throws StandardException { ResultSetNode retval; if (sourceResultSet instanceof FromTable) { FromList optList = (FromList) getNodeFactory().getNode( C_NodeTypes.FROM_LIST, getNodeFactory().doJoinOrderOptimization(), sourceResultSet, getContextManager()); /* If there is no predicate list, create an empty one */ if (predList == null) predList = (PredicateList) getNodeFactory().getNode( C_NodeTypes.PREDICATE_LIST, getContextManager()); LanguageConnectionContext lcc = getLanguageConnectionContext(); OptimizerFactory optimizerFactory = lcc.getOptimizerFactory(); optimizer = optimizerFactory.getOptimizer(optList, predList, getDataDictionary(), (RequiredRowOrdering) null, getCompilerContext().getNumTables(), lcc); optimizer.prepForNextRound(); if (sourceResultSet == leftResultSet) { leftOptimizer = optimizer; } else if (sourceResultSet == rightResultSet) { rightOptimizer = optimizer; } else { if (SanityManager.DEBUG) SanityManager.THROWASSERT("Result set being optimized is neither left nor right"); } /* ** Set the estimated number of outer rows from the outer part of ** the plan. */ optimizer.setOuterRows(outerCost.rowCount()); /* Optimize the underlying result set */ while (optimizer.getNextPermutation()) { while (optimizer.getNextDecoratedPermutation()) { optimizer.costPermutation(); } } retval = sourceResultSet; } else { retval = sourceResultSet.optimize( optimizer.getDataDictionary(), predList, outerCost.rowCount()); } return retval; } /** * Decrement (query block) level (0-based) for * all of the tables in this ResultSet tree. * This is useful when flattening a subquery. * * @param decrement The amount to decrement by. * * @return Nothing; */ void decrementLevel(int decrement) { leftResultSet.decrementLevel(decrement); rightResultSet.decrementLevel(decrement); } /** * Replace any DEFAULTs with the associated tree for the default. * * @param ttd The TableDescriptor for the target table. * @param tcl The RCL for the target table. * * @exception StandardException Thrown on error */ void replaceDefaults(TableDescriptor ttd, ResultColumnList tcl) throws StandardException { leftResultSet.replaceDefaults(ttd, tcl); rightResultSet.replaceDefaults(ttd, tcl); } /** * Notify the underlying result set tree that the result is * ordering dependent. (For example, no bulk fetch on an index * if under an IndexRowToBaseRow.) * * @return Nothing. */ void markOrderingDependent() { leftResultSet.markOrderingDependent(); rightResultSet.markOrderingDependent(); } /** * Accept a visitor, and call v.visit() * on child nodes as necessary. * * @param v the visitor * * @exception StandardException on error */ public Visitable accept(Visitor v) throws StandardException { if (v.skipChildren(this)) { return v.visit(this); } Visitable returnNode = super.accept(v); if (leftResultSet != null && !v.stopTraversal()) { leftResultSet = (ResultSetNode)leftResultSet.accept(v); } if (rightResultSet != null && !v.stopTraversal()) { rightResultSet = (ResultSetNode)rightResultSet.accept(v); } return returnNode; } /** * apparently something special needs to be done for me.... */ public boolean needsSpecialRCLBinding() { return true; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -