📄 predicatelist.java
字号:
for (int index = 0; index < size; index++) { predicate = (Predicate) elementAt(index); if (SanityManager.DEBUG) { SanityManager.ASSERT( fromMap.size() == predicate.getReferencedSet().size(), "fromMap.size() (" + fromMap.size() + ") does not equal predicate.getReferencedSet().size() (" + predicate.getReferencedSet().size()); } predicate.getReferencedSet().xor(fromMap); } } private void countScanFlags() { Predicate predicate; int size = size(); for (int index = 0; index < size; index++) { predicate = (Predicate) elementAt(index); if (predicate.isStartKey()) numberOfStartPredicates++; if (predicate.isStopKey()) numberOfStopPredicates++; if (predicate.isQualifier()) numberOfQualifiers++; } } /** * Push all predicates, which can be pushed, into the underlying select. * A predicate can be pushed into an underlying select if the source of * every ColumnReference in the predicate is itself a ColumnReference. * * This is useful when attempting to push predicates into non-flattenable * views or derived tables or into unions. * * @param select The underlying SelectNode. * @param copyPredicate Whether to make a copy of the predicate * before pushing * * @return Nothing. * * @exception StandardException Thrown on error */ void pushExpressionsIntoSelect(SelectNode select, boolean copyPredicate) throws StandardException { /* Walk list backwards since we can delete while * traversing the list. */ for (int index = size() - 1; index >= 0; index--) { Predicate predicate; predicate = (Predicate) elementAt(index); CollectNodesVisitor getCRs = new CollectNodesVisitor(ColumnReference.class); predicate.getAndNode().accept(getCRs); Vector colRefs = getCRs.getList(); /* state doesn't become true until we find the 1st * ColumnReference. (We probably will always find * at least 1 CR, but just to be safe, ...) */ boolean state = colRefs.size() > 0; if (state) { for (Enumeration e = colRefs.elements(); e.hasMoreElements(); ) { ColumnReference ref = (ColumnReference)e.nextElement(); if (!ref.pointsToColumnReference()) { state = false; break; } } } if (!state) continue; if (copyPredicate) { // Copy this predicate and push this instead AndNode andNode = predicate.getAndNode(); ValueNode leftOperand; ColumnReference crNode; BinaryRelationalOperatorNode opNode=null; InListOperatorNode inNode=null; // Make sure we are only pushing binary relations and InList for // copyPredicate case. It should be benificial to push expressions that // can be pushed, so they can be applied closer to the data. if (andNode.getLeftOperand() instanceof BinaryRelationalOperatorNode) { opNode = (BinaryRelationalOperatorNode) andNode.getLeftOperand(); // Investigate using invariant interface to check rightOperand if (! (opNode.getLeftOperand() instanceof ColumnReference) || ! (opNode.getRightOperand() instanceof ConstantNode || opNode.getRightOperand() instanceof ParameterNode)) continue; crNode = (ColumnReference) opNode.getLeftOperand(); } else if (andNode.getLeftOperand() instanceof InListOperatorNode) { inNode = (InListOperatorNode) andNode.getLeftOperand(); if (! (inNode.getRightOperandList().isConstantExpression())) continue; crNode = (ColumnReference) inNode.getLeftOperand(); } else continue; // Remap this crNode to underlying column reference in the select, if possible. ColumnReference newCRNode = select.findColumnReferenceInResult(crNode.columnName); if (newCRNode == null) continue; // Create a copy of the predicate to push down // <column> <relop> <value> AND TRUE if (andNode.getLeftOperand() instanceof BinaryRelationalOperatorNode) { BinaryRelationalOperatorNode newRelop = (BinaryRelationalOperatorNode) getNodeFactory().getNode( opNode.getNodeType(), newCRNode, opNode.getRightOperand(), getContextManager()); newRelop.bindComparisonOperator(); leftOperand = newRelop; } else { InListOperatorNode newInNode = (InListOperatorNode) getNodeFactory().getNode( C_NodeTypes.IN_LIST_OPERATOR_NODE, newCRNode, inNode.getRightOperandList(), getContextManager()); newInNode.setType(inNode.getTypeServices()); leftOperand = newInNode; } // Convert the predicate into CNF form ValueNode trueNode = (ValueNode) getNodeFactory().getNode( C_NodeTypes.BOOLEAN_CONSTANT_NODE, Boolean.TRUE, getContextManager()); AndNode newAnd = (AndNode) getNodeFactory().getNode( C_NodeTypes.AND_NODE, leftOperand, trueNode, getContextManager()); newAnd.postBindFixup(); JBitSet tableMap = new JBitSet(select.referencedTableMap.size()); // Use newly constructed predicate predicate = (Predicate) getNodeFactory().getNode( C_NodeTypes.PREDICATE, newAnd, tableMap, getContextManager()); } else { // keep the counters up to date when removing a predicate if (predicate.isStartKey()) numberOfStartPredicates--; if (predicate.isStopKey()) numberOfStopPredicates--; if (predicate.isQualifier()) numberOfQualifiers--; /* Clear all of the scan flags since they may be different * due to the splitting of the list. */ predicate.clearScanFlags(); // Remove this predicate from the list removeElementAt(index); } // Push it into the select select.pushExpressionsIntoSelect(predicate); } } /** * Mark all of the RCs and the RCs in their RC/VCN chain * referenced in the predicate list as referenced. * * @return Nothing. * * @exception StandardException Thrown on error */ void markReferencedColumns() throws StandardException { CollectNodesVisitor collectCRs = new CollectNodesVisitor(ColumnReference.class); int size = size(); for (int index = 0; index < size; index++) { Predicate predicate = (Predicate) elementAt(index); predicate.getAndNode().accept(collectCRs); } Vector colRefs = collectCRs.getList(); for (Enumeration e = colRefs.elements(); e.hasMoreElements(); ) { ColumnReference ref = (ColumnReference)e.nextElement(); ref.getSource().markAllRCsInChainReferenced(); } } /** * Update the array of columns in = conditions with constants * or correlation or join columns. This is useful when doing * subquery flattening on the basis of an equality condition. * * @param tableNumber The tableNumber of the table from which * the columns of interest come from. * @param eqAllCols Array of booleans for noting which columns * are in = predicates, regardless of the source * of the columns being joined with. * @param eqOuterCols Array of booleans for noting which columns * are in = predicates with constants or * correlation columns. * @param tableNumbers Array of table numbers in this query block. * @param resultColTable tableNumber is the table the result columns are * coming from * * @return Nothing. * * @exception StandardException Thrown on error */ void checkTopPredicatesForEqualsConditions( int tableNumber, boolean[] eqOuterCols, int[] tableNumbers, JBitSet[] tableColMap, boolean resultColTable) throws StandardException { int size = size(); for (int index = 0; index < size; index++) { AndNode and = (AndNode) ((Predicate) elementAt(index)).getAndNode(); and.checkTopPredicatesForEqualsConditions( tableNumber, eqOuterCols, tableNumbers, tableColMap, resultColTable); } } /** * Check if all of the predicates in the list are pushable. * * @return Whether or not all of the predicates in the list are pushable. */ boolean allPushable() { int size = size(); for (int index = 0; index < size; index++) { Predicate predicate = (Predicate) elementAt(index); if (! predicate.getPushable()) { return false; } } return true; } /** * Build a list of pushable predicates, if any, * that satisfy the referencedTableMap. * * @param referencedTableMap The referenced table map * * @return A list of pushable predicates, if any, * that satisfy the referencedTableMap. * * @exception StandardException Thrown on error */ PredicateList getPushablePredicates(JBitSet referencedTableMap) throws StandardException { PredicateList pushPList = null; // Walk the list backwards because of possible deletes for (int index = size() - 1; index >= 0; index--) { Predicate predicate = (Predicate) elementAt(index); if (! predicate.getPushable()) { continue; } JBitSet curBitSet = predicate.getReferencedSet(); /* Do we have a match? */ if (referencedTableMap.contains(curBitSet)) { /* Add the matching predicate to the push list */ if (pushPList == null) { pushPList = (PredicateList) getNodeFactory().getNode( C_NodeTypes.PREDICATE_LIST, getContextManager()); } pushPList.addPredicate(predicate); /* Remap all of the ColumnReferences to point to the * source of the values. */ RemapCRsVisitor rcrv = new RemapCRsVisitor(true); predicate.getAndNode().accept(rcrv); /* Remove the matching predicate from the outer list */ removeElementAt(index); } } return pushPList; } /** * Decrement the level of any CRs from the subquery's * FROM list that are interesting to transitive closure. * * @param fromList The subquery's FROM list. * @param decrement Decrement size. * * @return Nothing. */ void decrementLevel(FromList fromList, int decrement) { int[] tableNumbers = fromList.getTableNumbers(); /* For each top level relop, find all top level * CRs from the subquery and decrement their * nesting level. */ int size = size(); for (int index = 0; index < size; index++) { ColumnReference cr1 = null; ColumnReference cr2 = null; Predicate predicate = (Predicate) elementAt(index); ValueNode vn = predicate.getAndNode().getLeftOperand(); if (vn instanceof BinaryOperatorNode) { BinaryOperatorNode bon = (BinaryOperatorNode) vn; if (bon.getLeftOperand() instanceof ColumnReference) { cr1 = (ColumnReference) bon.getLeftOperand(); } if (bon.getRightOperand() instanceof ColumnReference) { cr2 = (ColumnReference) bon.getRightOperand(); } } else if (vn instanceof UnaryOperatorNode) { UnaryOperatorNode uon = (UnaryOperatorNode) vn; if (uon.getOperand() instanceof ColumnReference) { cr1 = (ColumnReference) uon.getOperand(); } } /* See if any of the CRs need to have their * source level decremented. */ if (cr1 != null) { int sourceTable = cr1.getTableNumber(); for (int inner = 0; inner < tableNumbers.length; inner++) if (tableNumbers[inner] == sourceTable) { cr1.setSourceLevel( cr1.getSourceLevel() - decrement); break; } } if (cr2 != null) { int sourceTable = cr2.getTableNumber(); for (int inner = 0; inner < tableNumbers.length; inner++) if (tableNumbers[inner] == sourceTable) { cr2.setSourceLevel( cr2.getSourceLevel() - decrement); break; } } } } /** * Perform transitive closure on join clauses. For each table in the query, * we build a list of equijoin clauses of the form: * <ColumnReference> <=> <ColumnReference> * Each join clause is put on 2 lists since it joins 2 tables. * * We then walk the array of lists. We first walk it as the outer list. * For each equijoin predicate, we assign an equivalence class if it does * not yet have one. We then walk the predicate list (as middle) for the * other table, searching for other equijoins with the middle table number * and column number. All such predicates are assigned the same * equivalence class. We then walk the predicate list (as inner) for the * other side of the middle predicate to see if we can find an equijoin * between outer and inner. If so, then we simply assign it to the same * equivalence class. If not, then we add the new equijoin clause. * * @param numTables The number of tables in the query * @param fromList The FromList in question. * @param cc The CompilerContext to use * * @return Nothing. * * @exception StandardException Thrown on error */ void joinClauseTransitiveClosure(int numTables, FromList fromList, CompilerContext cc) throws StandardException { // Nothing to do if < 3 tables if (fromList.size() < 3) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -