📄 subquerynode.java
字号:
rightIsNull.bindComparisonOperator(); newOr = (OrNode) getNodeFactory().getNode( C_NodeTypes.OR_NODE, rightIsNull, andLeft, getContextManager()); newOr.postBindFixup(); andLeft = newOr; } } } /* Place an AndNode above the <BinaryComparisonOperator> */ andNode = (AndNode) getNodeFactory().getNode( C_NodeTypes.AND_NODE, andLeft, getTrueNode(), getContextManager()); /* Build the referenced table map for the new predicate */ tableMap = new JBitSet(numTables); andNode.postBindFixup(); /* Put the AndNode under a Predicate */ predicate = (Predicate) getNodeFactory().getNode( C_NodeTypes.PREDICATE, andNode, tableMap, getContextManager()); predicate.categorize(); /* Push the new Predicate to the subquery's list */ resultSet = resultSet.addNewPredicate(predicate); /* Clean up the leftOperand and subquery ResultColumn */ leftOperand = null; firstRC.setType(getTypeServices()); firstRC.setExpression(getTrueNode()); /* Add the IS [NOT] NULL above the SubqueryNode */ switch (subqueryType) { case IN_SUBQUERY: case EQ_ANY_SUBQUERY: case NE_ANY_SUBQUERY: case LE_ANY_SUBQUERY: case LT_ANY_SUBQUERY: case GE_ANY_SUBQUERY: case GT_ANY_SUBQUERY: ucoNode = (UnaryComparisonOperatorNode) getNodeFactory().getNode( C_NodeTypes.IS_NOT_NULL_NODE, this, getContextManager()); break; case NOT_IN_SUBQUERY: case EQ_ALL_SUBQUERY: case NE_ALL_SUBQUERY: case LE_ALL_SUBQUERY: case LT_ALL_SUBQUERY: case GE_ALL_SUBQUERY: case GT_ALL_SUBQUERY: ucoNode = (UnaryComparisonOperatorNode) getNodeFactory().getNode( C_NodeTypes.IS_NULL_NODE, this, getContextManager()); break; } ucoNode.bindComparisonOperator(); return ucoNode; } /** * Build a new join condition between the leftOperand * and the rightOperand. The comparison operator * is dependent on the subquery type. * * @param leftOperand The left operand for the new condition. * @param rightOperand The right operand for the new condition. * * @exception StandardException Thrown on error */ private BinaryComparisonOperatorNode getNewJoinCondition( ValueNode leftOperand, ValueNode rightOperand) throws StandardException { BinaryComparisonOperatorNode bcoNode = null; /* NOTE: If we are an expression subquery that's getting * flattened then our subqueryType is EXPRESSION_SUBQUERY. * However, we can get the comparison type from the * parentComparisonOperator. In that case we dovetail on * the ANY subquery types. */ int operatorType = subqueryType; if (subqueryType == EXPRESSION_SUBQUERY) { if (SanityManager.DEBUG) { SanityManager.ASSERT(parentComparisonOperator != null, "parentComparisonOperator expected to be non-null"); } int parentOperator = -1; if (parentComparisonOperator.isRelationalOperator()) { RelationalOperator ro = (RelationalOperator)parentComparisonOperator; parentOperator = ro.getOperator(); } if (parentOperator == RelationalOperator.EQUALS_RELOP) { operatorType = EQ_ANY_SUBQUERY; } else if (parentOperator == RelationalOperator.NOT_EQUALS_RELOP) { operatorType = NE_ANY_SUBQUERY; } else if (parentOperator == RelationalOperator.LESS_EQUALS_RELOP) { operatorType = LE_ANY_SUBQUERY; } else if (parentOperator == RelationalOperator.LESS_THAN_RELOP) { operatorType = LT_ANY_SUBQUERY; } else if (parentOperator == RelationalOperator.GREATER_EQUALS_RELOP) { operatorType = GE_ANY_SUBQUERY; } else if (parentOperator == RelationalOperator.GREATER_THAN_RELOP) { operatorType = GT_ANY_SUBQUERY; } } int bcoType = 0; int nodeType = 0; /* Build the <BinaryComparisonOperator> */ switch (operatorType) { case IN_SUBQUERY: case EQ_ANY_SUBQUERY: case NOT_IN_SUBQUERY: case NE_ALL_SUBQUERY: nodeType = C_NodeTypes.BINARY_EQUALS_OPERATOR_NODE; break; case NE_ANY_SUBQUERY: case EQ_ALL_SUBQUERY: nodeType = C_NodeTypes.BINARY_NOT_EQUALS_OPERATOR_NODE; break; case LE_ANY_SUBQUERY: case GT_ALL_SUBQUERY: nodeType = C_NodeTypes.BINARY_LESS_EQUALS_OPERATOR_NODE; break; case LT_ANY_SUBQUERY: case GE_ALL_SUBQUERY: nodeType = C_NodeTypes.BINARY_LESS_THAN_OPERATOR_NODE; break; case GE_ANY_SUBQUERY: case LT_ALL_SUBQUERY: nodeType = C_NodeTypes.BINARY_GREATER_EQUALS_OPERATOR_NODE; break; case GT_ANY_SUBQUERY: case LE_ALL_SUBQUERY: nodeType = C_NodeTypes.BINARY_GREATER_THAN_OPERATOR_NODE; break; default: if (SanityManager.DEBUG) SanityManager.ASSERT(false, "subqueryType (" + subqueryType + ") is an unexpected type"); } bcoNode = (BinaryComparisonOperatorNode) getNodeFactory().getNode( nodeType, leftOperand, rightOperand, getContextManager()); bcoNode.bindComparisonOperator(); return bcoNode; } /** * Eliminate NotNodes in the current query block. We traverse the tree, * inverting ANDs and ORs and eliminating NOTs as we go. We stop at * ComparisonOperators and boolean expressions. We invert * ComparisonOperators and replace boolean expressions with * boolean expression = false. * NOTE: Since we do not recurse under ComparisonOperators, there * still could be NotNodes left in the tree. * * @param underNotNode Whether or not we are under a NotNode. * * * @return The modified expression * * @exception StandardException Thrown on error */ ValueNode eliminateNots(boolean underNotNode) throws StandardException { ValueNode result = this; if (underNotNode) { /* Negate the subqueryType. For expression subqueries * we simply return subquery = false */ /* RESOLVE - This code needs to get cleaned up once there are * more subquery types. (Consider using arrays.) */ switch (subqueryType) { case EXPRESSION_SUBQUERY: result = genEqualsFalseTree(); break; case EXISTS_SUBQUERY: subqueryType = NOT_EXISTS_SUBQUERY; break; /* ANY subqueries */ case IN_SUBQUERY: case EQ_ANY_SUBQUERY: subqueryType = NOT_IN_SUBQUERY; break; case NE_ANY_SUBQUERY: subqueryType = EQ_ALL_SUBQUERY; break; case GE_ANY_SUBQUERY: subqueryType = LT_ALL_SUBQUERY; break; case GT_ANY_SUBQUERY: subqueryType = LE_ALL_SUBQUERY; break; case LE_ANY_SUBQUERY: subqueryType = GT_ALL_SUBQUERY; break; case LT_ANY_SUBQUERY: subqueryType = GE_ALL_SUBQUERY; break; /* ALL subqueries - no need for NOT NOT_IN_SUBQUERY, since * NOT IN only comes into existence here. */ case EQ_ALL_SUBQUERY: subqueryType = NE_ANY_SUBQUERY; break; case NE_ALL_SUBQUERY: subqueryType = EQ_ANY_SUBQUERY; break; case GE_ALL_SUBQUERY: subqueryType = LT_ANY_SUBQUERY; break; case GT_ALL_SUBQUERY: subqueryType = LE_ANY_SUBQUERY; break; case LE_ALL_SUBQUERY: subqueryType = GT_ANY_SUBQUERY; break; case LT_ALL_SUBQUERY: subqueryType = GE_ANY_SUBQUERY; break; default: if (SanityManager.DEBUG) SanityManager.ASSERT(false, "NOT is not supported for this time of subquery"); } } /* Halt recursion here, as each query block is preprocessed separately */ return result; } /** * Finish putting an expression into conjunctive normal * form. An expression tree in conjunctive normal form meets * the following criteria: * o If the expression tree is not null, * the top level will be a chain of AndNodes terminating * in a true BooleanConstantNode. * o The left child of an AndNode will never be an AndNode. * o Any right-linked chain that includes an AndNode will * be entirely composed of AndNodes terminated by a true BooleanConstantNode. * o The left child of an OrNode will never be an OrNode. * o Any right-linked chain that includes an OrNode will * be entirely composed of OrNodes terminated by a false BooleanConstantNode. * o ValueNodes other than AndNodes and OrNodes are considered * leaf nodes for purposes of expression normalization. * In other words, we won't do any normalization under * those nodes. * * In addition, we track whether or not we are under a top level AndNode. * SubqueryNodes need to know this for subquery flattening. * * @param underTopAndNode Whether or not we are under a top level AndNode. * * * @return The modified expression * * @exception StandardException Thrown on error */ public ValueNode changeToCNF(boolean underTopAndNode) throws StandardException { /* Remember whether or not we are immediately under a top leve * AndNode. This is important for subquery flattening. * (We can only flatten subqueries under a top level AndNode.) */ this.underTopAndNode = underTopAndNode; /* Halt recursion here, as each query block is preprocessed separately */ return this; } /** * Categorize this predicate. Initially, this means * building a bit map of the referenced tables for each predicate. * If the source of this ColumnReference (at the next underlying level) * is not a ColumnReference or a VirtualColumnNode then this predicate * will not be pushed down. * * For example, in: * select * from (select 1 from s) a (x) where x = 1 * we will not push down x = 1. * NOTE: It would be easy to handle the case of a constant, but if the * inner SELECT returns an arbitrary expression, then we would have to copy * that tree into the pushed predicate, and that tree could contain * subqueries and method calls. * RESOLVE - revisit this issue once we have views. * * @param referencedTabs JBitSet with bit map of referenced FromTables * @return boolean Whether or not source.expression is a ColumnReference * or a VirtualColumnNode. * * @exception StandardException Thrown on error */ public boolean categorize(JBitSet referencedTabs, boolean simplePredsOnly) throws StandardException { /* We stop here when only considering simple predicates * as we don't consider method calls when looking * for null invariant predicates. */ if (simplePredsOnly) { return false; } /* RESOLVE - We need to or in a bit map when there are correlation columns */ /* We categorize a query block at a time, so stop the recursion here */ /* Predicates with subqueries are not pushable for now */ /* ** If we can materialize the subquery, then it is ** both invariant and non-correlated. And so it ** is pushable. */ return isMaterializable(); } /* ** Subquery is materializable if ** it is an expression subquery that ** has no correlations and is invariant. */ boolean isMaterializable() throws StandardException { boolean retval = (subqueryType == EXPRESSION_SUBQUERY) && !hasCorrelatedCRs() && isInvariant(); /* If we can materialize the subquery, then we set * the level of all of the tables to 0 so that we can * consider bulk fetch for them. */ if (retval) { if (resultSet instanceof SelectNode) { SelectNode select = (SelectNode) resultSet; FromList fromList = select.getFromList(); fromList.setLevel(0); } } return retval; } /** * Optimize this SubqueryNode. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -