From cbf503180fda16cd4688ddfa67b6ea2b6eafef25 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 31 May 2000 15:38:53 +0000
Subject: [PATCH] Tweak recognition of range-clause pairs so that 'var > $1 AND
 var < $2' (ie, parameters instead of consts) will be treated as a range
 query. We do not know the actual selectivities involved, but it seems like a
 good idea to use a smaller estimate than we would use for two unrelated
 inequalities.

---
 src/backend/optimizer/path/clausesel.c | 83 ++++++++++++++------------
 1 file changed, 46 insertions(+), 37 deletions(-)

diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index 95b9ba4b90d..62a5b0295c3 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.36 2000/05/30 00:49:46 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.37 2000/05/31 15:38:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -95,7 +95,7 @@ restrictlist_selectivity(Query *root,
  * directly as a 0..1 value but we need to convert losel to 1-losel before
  * interpreting it as a value.	Then the available range is 1-losel to hisel.)
  * If the calculation yields zero or negative, however, we chicken out and
- * use the default interpretation; that probably means that one or both
+ * use a default estimate; that probably means that one or both
  * selectivities is a default estimate rather than an actual range value.
  * Of course this is all very dependent on the behavior of
  * scalarltsel/scalargtsel; perhaps some day we can generalize the approach.
@@ -120,10 +120,12 @@ clauselist_selectivity(Query *root,
 		Selectivity s2;
 
 		/*
-		 * See if it looks like a restriction clause with a constant. (If
-		 * it's not a constant we can't really trust the selectivity!) NB:
-		 * for consistency of results, this fragment of code had better
-		 * match what clause_selectivity() would do.
+		 * See if it looks like a restriction clause with a Const or Param
+		 * on one side.  (Anything more complicated than that might not
+		 * behave in the simple way we are expecting.)
+		 *
+		 * NB: for consistency of results, this fragment of code had better
+		 * match what clause_selectivity() would do in the cases it handles.
 		 */
 		if (varRelid != 0 || NumRelids(clause) == 1)
 		{
@@ -134,41 +136,48 @@ clauselist_selectivity(Query *root,
 
 			get_relattval(clause, varRelid,
 						  &relidx, &attno, &constval, &flag);
-			if (relidx != 0 && (flag & SEL_CONSTANT))
+			if (relidx != 0)
 			{
 				/* if get_relattval succeeded, it must be an opclause */
-				Oid			opno = ((Oper *) ((Expr *) clause)->oper)->opno;
-				RegProcedure oprrest = get_oprrest(opno);
+				Var		   *other;
 
-				if (!oprrest)
-					s2 = (Selectivity) 0.5;
-				else
-					s2 = restriction_selectivity(oprrest, opno,
-												 getrelid(relidx,
-														  root->rtable),
-												 attno,
-												 constval, flag);
-
-				/*
-				 * If we reach here, we have computed the same result that
-				 * clause_selectivity would, so we can just use s2 if it's
-				 * the wrong oprrest.  But if it's the right oprrest, add
-				 * the clause to rqlist for later processing.
-				 */
-				switch (oprrest)
+				other = (flag & SEL_RIGHT) ? get_rightop((Expr *) clause) :
+					get_leftop((Expr *) clause);
+				if (IsA(other, Const) || IsA(other, Param))
 				{
-					case F_SCALARLTSEL:
-						addRangeClause(&rqlist, clause, flag, true, s2);
-						break;
-					case F_SCALARGTSEL:
-						addRangeClause(&rqlist, clause, flag, false, s2);
-						break;
-					default:
-						/* Just merge the selectivity in generically */
-						s1 = s1 * s2;
-						break;
+					Oid		opno = ((Oper *) ((Expr *) clause)->oper)->opno;
+					RegProcedure oprrest = get_oprrest(opno);
+
+					if (!oprrest)
+						s2 = (Selectivity) 0.5;
+					else
+						s2 = restriction_selectivity(oprrest, opno,
+													 getrelid(relidx,
+															  root->rtable),
+													 attno,
+													 constval, flag);
+
+					/*
+					 * If we reach here, we have computed the same result that
+					 * clause_selectivity would, so we can just use s2 if it's
+					 * the wrong oprrest.  But if it's the right oprrest, add
+					 * the clause to rqlist for later processing.
+					 */
+					switch (oprrest)
+					{
+						case F_SCALARLTSEL:
+							addRangeClause(&rqlist, clause, flag, true, s2);
+							break;
+						case F_SCALARGTSEL:
+							addRangeClause(&rqlist, clause, flag, false, s2);
+							break;
+						default:
+							/* Just merge the selectivity in generically */
+							s1 = s1 * s2;
+							break;
+					}
+					continue;	/* drop to loop bottom */
 				}
-				continue;		/* drop to loop bottom */
 			}
 		}
 		/* Not the right form, so treat it generically. */
@@ -374,7 +383,7 @@ clause_selectivity(Query *root,
 										 BooleanEqualOperator,
 										 getrelid(varno, root->rtable),
 										 ((Var *) clause)->varattno,
-										 Int8GetDatum(true),
+										 BoolGetDatum(true),
 										 SEL_CONSTANT | SEL_RIGHT);
 		/* an outer-relation bool var is taken as always true... */
 	}
-- 
GitLab