📄 halfouterjoinnode.java
字号:
refCheck = true; } else if (leftOperandCheck == true && NPReferencedTableMap.get(((ColumnReference)rightCol).getTableNumber())) { refCheck = true; } if (refCheck == false) return LOJ_bindResultColumns(anyChange); } else return LOJ_bindResultColumns(anyChange); // get out of here vn = and.getRightOperand(); } // Check if the logical right resultset is a composite inner and as such // that this current LOJ can be pushed through it. boolean push = false; // logical right operand is another LOJ... so we may be able to push the // join if (logicalRightResultSet instanceof HalfOuterJoinNode) { // get the Null-producing operand of the child JBitSet logicalNPRefTableMap = ((HalfOuterJoinNode)logicalRightResultSet).LOJgetNPReferencedTables(numTables); // does the current LOJ join predicate reference // logicalNPRefTableMap? If not, we can push the current // join. vn = joinClause; push = true; while (vn instanceof AndNode) { and = (AndNode) vn; left = and.getLeftOperand(); equals = (BinaryRelationalOperatorNode) left; leftCol = equals.getLeftOperand(); rightCol = equals.getRightOperand(); if (logicalNPRefTableMap.get(((ColumnReference)leftCol).getTableNumber()) || logicalNPRefTableMap.get(((ColumnReference)rightCol).getTableNumber())) { push = false; break; } vn = and.getRightOperand(); } } // Push the current LOJ into the next level if (push) { // For safety, check the JoinNode data members: they should null or // empty list before we proceed. if (super.subqueryList.size() != 0 || ((JoinNode)logicalRightResultSet).subqueryList.size() != 0 || super.joinPredicates.size() != 0 || ((JoinNode)logicalRightResultSet).joinPredicates.size() != 0 || super.usingClause != null || ((JoinNode)logicalRightResultSet).usingClause != null) return LOJ_bindResultColumns(anyChange); // get out of here anyChange = true; // we are reordering the LOJs. ResultSetNode tmp = logicalLeftResultSet; ResultSetNode LChild, RChild; // this LOJ // / \ // logicalLeftRS LogicalRightRS // / \ // LChild RChild // becomes // // this LOJ // / \ // LogicalRightRS RChild // / \ // logicalLeftRS LChild <<< we need to be careful about this order // as the "LogicalRightRS may be a ROJ // // handle the lower level LOJ node LChild = ((HalfOuterJoinNode)logicalRightResultSet).leftResultSet; RChild = ((HalfOuterJoinNode)logicalRightResultSet).rightResultSet; ((HalfOuterJoinNode)logicalRightResultSet).rightResultSet = LChild; ((HalfOuterJoinNode)logicalRightResultSet).leftResultSet = tmp; // switch the ON clause vn = joinClause; joinClause = ((HalfOuterJoinNode)logicalRightResultSet).joinClause; ((HalfOuterJoinNode)logicalRightResultSet).joinClause = vn; // No need to switch HalfOuterJoinNode data members for now because // we are handling only LOJ. // boolean local_rightOuterJoin = rightOuterJoin; // boolean local_transformed = transformed; // rightOuterJoin = ((HalfOuterJoinNode)logicalRightResultSet).rightOuterJoin; // transformed = ((HalfOuterJoinNode)logicalRightResultSet).transformed; // ((HalfOuterJoinNode)logicalRightResultSet).rightOuterJoin = local_rightOuterJoin; // ((HalfOuterJoinNode)logicalRightResultSet).transformed = local_transformed; FromList localFromList = (FromList) getNodeFactory().getNode( C_NodeTypes.FROM_LIST, getNodeFactory().doJoinOrderOptimization(), getContextManager()); // switch LOJ nodes: by handling the current LOJ node leftResultSet = logicalRightResultSet; rightResultSet = RChild; // rebuild the result columns and re-bind column references ((HalfOuterJoinNode)leftResultSet).resultColumns = null; ((JoinNode)leftResultSet).bindResultColumns(localFromList); // localFromList is empty // left operand must be another LOJ, try again until a fixpoint boolean localChange = ((HalfOuterJoinNode)leftResultSet).LOJ_reorderable(numTables); // rebuild the result columns and re-bind column references for 'this' return LOJ_bindResultColumns(anyChange); } return LOJ_bindResultColumns(anyChange); } // This method re-binds the result columns which may be referenced in the ON // clause in this node. public boolean LOJ_bindResultColumns(boolean anyChange) throws StandardException { if (anyChange) { this.resultColumns = null; FromList localFromList = (FromList) getNodeFactory().getNode(C_NodeTypes.FROM_LIST, getNodeFactory().doJoinOrderOptimization(), getContextManager()); ((JoinNode)this).bindResultColumns(localFromList); } return anyChange; } /** * Transform any Outer Join into an Inner Join where applicable. * (Based on the existence of a null intolerant * predicate on the inner table.) * * @param predicateTree The predicate tree for the query block * * @return The new tree top (OuterJoin or InnerJoin). * * @exception StandardException Thrown on error */ public FromTable transformOuterJoins(ValueNode predicateTree, int numTables) throws StandardException { ResultSetNode innerRS; if (predicateTree == null) { /* We can't transform this node, so tell both sides of the * outer join that they can't get flattened into outer query block. */ leftResultSet.notFlattenableJoin(); rightResultSet.notFlattenableJoin(); return this; } super.transformOuterJoins(predicateTree, numTables); JBitSet innerMap = new JBitSet(numTables); if (rightOuterJoin) { if (SanityManager.DEBUG) { SanityManager.ASSERT(! transformed, "right OJ not expected to be transformed into left OJ yet"); } innerRS = leftResultSet; } else { innerRS = rightResultSet; } innerRS.fillInReferencedTableMap(innerMap); /* Walk predicates looking for * a null intolerant predicate on the inner table. */ ValueNode vn = predicateTree; while (vn instanceof AndNode) { AndNode and = (AndNode) vn; ValueNode left = and.getLeftOperand(); /* Skip IS NULL predicates as they are not null intolerant */ if (left.isInstanceOf(C_NodeTypes.IS_NULL_NODE)) { vn = and.getRightOperand(); continue; } /* Only consider predicates that are relops */ if (left instanceof RelationalOperator) { JBitSet refMap = new JBitSet(numTables); /* Do not consider method calls, * conditionals, field references, etc. */ if (! (left.categorize(refMap, true))) { vn = and.getRightOperand(); continue; } /* If the predicate is a null intolerant predicate * on the right side then we can flatten to an * inner join. We do the xform here, flattening * will happen later. */ for (int bit = 0; bit < numTables; bit++) { if (refMap.get(bit) && innerMap.get(bit)) { // OJ -> IJ JoinNode ij = (JoinNode) getNodeFactory().getNode( C_NodeTypes.JOIN_NODE, leftResultSet, rightResultSet, joinClause, null, resultColumns, null, getContextManager()); ij.setTableNumber(tableNumber); ij.setSubqueryList(subqueryList); ij.setAggregateVector(aggregateVector); return ij; } } } vn = and.getRightOperand(); } /* We can't transform this node, so tell both sides of the * outer join that they can't get flattened into outer query block. */ leftResultSet.notFlattenableJoin(); rightResultSet.notFlattenableJoin(); return this; } /** @see JoinNode#adjustNumberOfRowsReturned */ protected void adjustNumberOfRowsReturned(CostEstimate costEstimate) { /* ** An outer join returns at least as many rows as in the outer ** table. Even if this started as a right outer join, it will ** have been transformed to a left outer join by this point. */ CostEstimate outerCost = getLeftResultSet().getCostEstimate(); if (costEstimate.rowCount() < outerCost.rowCount()) { costEstimate.setCost(costEstimate.getEstimatedCost(), outerCost.rowCount(), outerCost.rowCount()); } } /** * Generate the code for an inner join node. * * @exception StandardException Thrown on error */ public void generate(ActivationClassBuilder acb, MethodBuilder mb) throws StandardException { /* Verify that a user specifed right outer join is transformed into * a left outer join exactly once. */ if (SanityManager.DEBUG) { SanityManager.ASSERT(rightOuterJoin == transformed, "rightOuterJoin (" + rightOuterJoin + ") is expected to equal transformed (" + transformed + ")"); } super.generateCore(acb, mb, LEFTOUTERJOIN); } /** * Generate and add any arguments specifict to outer joins. * Generate the methods (and add them as parameters) for * returning an empty row from 1 or more sides of an outer join, * if required. Pass whether or not this was originally a * right outer join. * * @param acb The ActivationClassBuilder * @param mb the method the generate code is to go into * * return The args that have been added * * @exception StandardException Thrown on error */ protected int addOuterJoinArguments(ActivationClassBuilder acb, MethodBuilder mb) throws StandardException { /* Nulls always generated from the right */ rightResultSet.getResultColumns().generateNulls(acb, mb); /* Was this originally a right outer join? */ mb.push(rightOuterJoin); return 2; } /** * Return the number of arguments to the join result set. */ protected int getNumJoinArguments() { /* We add two more arguments than the superclass does */ return super.getNumJoinArguments() + 2; } protected void oneRowRightSide(ActivationClassBuilder acb, MethodBuilder mb) { // always return false for now mb.push(false); mb.push(false); //isNotExists? } /** * Return the logical left result set for this qualified * join node. * (For RIGHT OUTER JOIN, the left is the right * and the right is the left and the JOIN is the NIOJ). */ ResultSetNode getLogicalLeftResultSet() { if (rightOuterJoin) { return rightResultSet; } else { return leftResultSet; } } /** * Return the logical right result set for this qualified * join node. * (For RIGHT OUTER JOIN, the left is the right * and the right is the left and the JOIN is the NIOJ). */ ResultSetNode getLogicalRightResultSet() { if (rightOuterJoin) { return leftResultSet; } else { return rightResultSet; } } /** * Return true if right outer join or false if left outer join * Used to set Nullability correctly in JoinNode */ public boolean isRightOuterJoin() { return rightOuterJoin; } // return the Null-producing table references public JBitSet LOJgetNPReferencedTables(int numTables) throws StandardException { if (rightOuterJoin && !transformed) return (JBitSet) leftResultSet.LOJgetReferencedTables(numTables); else return (JBitSet) rightResultSet.LOJgetReferencedTables(numTables); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -