You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ab...@apache.org on 2007/02/27 00:45:24 UTC

svn commit: r512079 - in /db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile: BinaryRelationalOperatorNode.java Predicate.java PredicateList.java

Author: abrown
Date: Mon Feb 26 15:45:22 2007
New Revision: 512079

URL: http://svn.apache.org/viewvc?view=rev&rev=512079
Log:
DERBY-47 (partial): First incremental patch for the multi-probing ("mp")
approach described in Jira comments. As mentioned in that comment, we need
to be able to distinguish between "true" relational predicates and "probe
predicates" so that we do not incorrectly perform certain operations on
probe predicates. This first patch adds the logic to allow such distinction.
In particular it:

  - Adds a new method, "isRelationalOpPredicate()", to Predicate.java that
    only returns true if the predicate is a "true" relational predicate; i.e.
    it will return "false" for probe predicates.

  - Updates several "if" statements in Predicate.java and PredicateList.java
    to use the new method.

  - Updates several utility methods in BinaryRelationalOperatorNode to distinguish
    "true" relational operators from ones that are created internally for probe
    predicates.

There should be no functional changes to Derby as a result of this patch.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryRelationalOperatorNode.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/Predicate.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryRelationalOperatorNode.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryRelationalOperatorNode.java?view=diff&rev=512079&r1=512078&r2=512079
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryRelationalOperatorNode.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/BinaryRelationalOperatorNode.java Mon Feb 26 15:45:22 2007
@@ -75,6 +75,16 @@
 	JBitSet optBaseTables;
 	JBitSet valNodeBaseTables;
 
+	/* If this BinRelOp was created for an IN-list "probe predicate"
+	 * then we keep a pointer to the original IN-list.  This serves
+	 * two purposes: 1) if this field is non-null then we know that
+	 * this BinRelOp is for an IN-list probe predicate; 2) if the
+	 * optimizer chooses a plan for which the probe predicate is
+	 * not usable as a start/stop key then we'll "revert" the pred
+	 * back to the InListOperatorNode referenced here.
+	 */
+	InListOperatorNode inListProbeSource = null;
+
 	public void init(Object leftOperand, Object rightOperand)
 	{
 		String methodName = "";
@@ -128,6 +138,29 @@
 		btnVis = null;
 	}
 
+	/**
+	 * Same as init() above except takes a third argument that is
+	 * an InListOperatorNode.  This version is used during IN-list
+	 * preprocessing to create a "probe predicate" for the IN-list.
+	 * See InListOperatorNode.preprocess() for more.
+	 */
+	public void init(Object leftOperand, Object rightOperand, Object inListOp)
+	{
+		init(leftOperand, rightOperand);
+		this.inListProbeSource = (InListOperatorNode)inListOp;
+	}
+
+	/**
+	 * If this rel op was created for an IN-list probe predicate then return
+	 * the underlying InListOperatorNode.  Will return null if this rel
+	 * op is a "legitimate" relational operator (as opposed to a disguised
+	 * IN-list).
+	 */
+	protected InListOperatorNode getInListOp()
+	{
+		return inListProbeSource;
+	}
+
 	/** @see RelationalOperator#getColumnOperand */
 	public ColumnReference getColumnOperand(
 								Optimizable optTable,
@@ -738,6 +771,17 @@
 	public boolean isQualifier(Optimizable optTable, boolean forPush)
 		throws StandardException
 	{
+		/* If this rel op is for an IN-list probe predicate then we never
+		 * treat it as a qualifer.  The reason is that if we treat it as
+		 * a qualifier then we could end up generating it as a qualifier,
+		 * which would lead to the generation of an equality qualifier
+		 * of the form "col = <val>" (where <val> is the first value in
+		 * the IN-list).  That would lead to wrong results (missing rows)
+		 * because that restriction is incorrect.
+		 */
+		if (inListProbeSource != null)
+			return false;
+
 		FromTable	ft;
 		ValueNode	otherSide = null;
 		JBitSet		tablesReferenced;
@@ -1169,12 +1213,22 @@
 	/** @see ValueNode#isRelationalOperator */
 	public boolean isRelationalOperator()
 	{
-		return true;
+		/* If this rel op is for a probe predicate then we do not call
+		 * it a "relational operator"; it's actually a disguised IN-list
+		 * operator.
+		 */
+		return (inListProbeSource == null);
 	}
 	
+	/** @see ValueNode#isBinaryEqualsOperatorNode */
 	public boolean isBinaryEqualsOperatorNode()
 	{
-		return (operatorType == RelationalOperator.EQUALS_RELOP);
+		/* If this rel op is for a probe predicate then we do not treat
+		 * it as an "equals operator"; it's actually a disguised IN-list
+		 * operator.
+		 */
+		return (inListProbeSource == null) &&
+			(operatorType == RelationalOperator.EQUALS_RELOP);
 	}
 
 	/** @see ValueNode#optimizableEqualityNode */
@@ -1184,6 +1238,12 @@
 		throws StandardException
 	{
 		if (operatorType != EQUALS_RELOP)
+			return false;
+
+		/* If this rel op is for a probe predicate then we do not treat
+		 * it as an equality node; it's actually a disguised IN-list node.
+		 */
+		if (inListProbeSource != null)
 			return false;
 
 		ColumnReference cr = getColumnOperand(optTable,

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/Predicate.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/Predicate.java?view=diff&rev=512079&r1=512078&r2=512079
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/Predicate.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/Predicate.java Mon Feb 26 15:45:22 2007
@@ -175,7 +175,7 @@
 		/* if this is for "in" operator node's dynamic start/stop key, relop is
 		 * null, and it's not comparing with constant, beetle 3858
 		 */
-		if (relop == null)
+		if (!isRelationalOpPredicate())
 			return false;
 
 		if (relop.compareWithKnownConstant(optTable, considerParameters))
@@ -190,7 +190,7 @@
 	{
 		RelationalOperator relop = getRelop();
 
-		if (relop == null)
+		if (!isRelationalOpPredicate())
 			return -1;
 		
 		if (!(relop.getOperator() == RelationalOperator.EQUALS_RELOP))
@@ -237,12 +237,11 @@
 	/** @see OptimizablePredicate#equalsComparisonWithConstantExpression */
 	public boolean equalsComparisonWithConstantExpression(Optimizable optTable)
 	{
-		RelationalOperator relop = getRelop();
 		boolean retval = false;
 
-		if (relop != null)
+		if (isRelationalOpPredicate())
 		{
-			retval = relop.equalsComparisonWithConstantExpression(optTable);
+			retval = getRelop().equalsComparisonWithConstantExpression(optTable);
 		}
 
 		return retval;
@@ -308,7 +307,7 @@
 		boolean thisIsEquals = false, otherIsEquals = false;
 		boolean thisIsNotEquals = true, otherIsNotEquals = true;
 
-		if (getRelop() != null)		// this is not "in"
+		if (this.isRelationalOpPredicate()) // this is not "in"
 		{
 			int thisOperator = ((RelationalOperator)andNode.getLeftOperand()).getOperator();
 			thisIsEquals = (thisOperator == RelationalOperator.EQUALS_RELOP ||
@@ -316,7 +315,7 @@
 			thisIsNotEquals = (thisOperator == RelationalOperator.NOT_EQUALS_RELOP ||
 								   thisOperator == RelationalOperator.IS_NOT_NULL_RELOP);
 		}
-		if (otherPred.getRelop() != null)		// other is not "in"
+		if (otherPred.isRelationalOpPredicate()) // other is not "in"
 		{
 			int	otherOperator = ((RelationalOperator)(otherPred.getAndNode().getLeftOperand())).getOperator();
 			otherIsEquals = (otherOperator == RelationalOperator.EQUALS_RELOP ||
@@ -1298,5 +1297,32 @@
 		exp = cRef.getSource().getExpression();
 		return ((exp instanceof VirtualColumnNode) ||
 			(exp instanceof ColumnReference));
+	}
+
+	/**
+	 * Return whether or not this predicate corresponds to a legitimate
+	 * relational operator.
+	 *
+	 * @return False if there is no relational operator for this predicate
+	 *  OR if this predicate is an internal "probe predicate" (in which
+	 *  case it "looks" like we have a relational operator but in truth
+	 *  it's a disguised IN-list operator). True otherwise.
+	 */
+	protected boolean isRelationalOpPredicate()
+	{
+		return ((getRelop() != null) && (getSourceInList() == null));
+	}
+
+	/**
+	 * If this predicate is an IN-list "probe predicate" then return
+	 * the InListOperatorNode from which it was built.  Otherwise
+	 * return null.
+	 */
+	protected InListOperatorNode getSourceInList()
+	{
+		RelationalOperator relop = getRelop();
+		if (relop instanceof BinaryRelationalOperatorNode)
+			return ((BinaryRelationalOperatorNode)relop).getInListOp();
+		return null;
 	}
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java?view=diff&rev=512079&r1=512078&r2=512079
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/compile/PredicateList.java Mon Feb 26 15:45:22 2007
@@ -534,9 +534,7 @@
 				** Skip over it if it's not a relational operator (this includes
 				** BinaryComparisonOperators and IsNullNodes.
 				*/
-				RelationalOperator relop = pred.getRelop();
-
-				if (relop == null)
+				if (!pred.isRelationalOpPredicate())
                 {
                     // possible OR clause, check for it.
 
@@ -548,7 +546,7 @@
                 }
                 else
                 {
-                    if ( ! relop.isQualifier(optTable, pushPreds))
+                    if ( ! pred.getRelop().isQualifier(optTable, pushPreds))
                     {
                         // NOT a qualifier, go on to next predicate.
                         continue;
@@ -944,9 +942,9 @@
 		{
 			Predicate	pred = (Predicate) elementAt(index);
 
-			RelationalOperator relop = pred.getRelop();
 			// Transfer each non-qualifier
-			if (relop == null || ! relop.isQualifier(optTable, false))
+			if (!pred.isRelationalOpPredicate() ||
+				!pred.getRelop().isQualifier(optTable, false))
 			{
 				pred.clearScanFlags();
 				removeElementAt(index);
@@ -2071,7 +2069,7 @@
 			AndNode			andNode = predicate.getAndNode();
 
 			// Skip anything that's not a RelationalOperator
-			if (! (andNode.getLeftOperand() instanceof RelationalOperator))
+			if (!predicate.isRelationalOpPredicate())
 			{
 				continue;
 			}
@@ -3396,7 +3394,7 @@
 			Predicate	pred = (Predicate) elementAt(index);
 			RelationalOperator relop = pred.getRelop();
 
-			if (relop != null)
+			if (pred.isRelationalOpPredicate())
 			{
 				if (relop.getOperator() == RelationalOperator.EQUALS_RELOP)
 				{