consider_vars.diff.no-cfbot

text/plain

Filename: consider_vars.diff.no-cfbot
Type: text/plain
Part: 0
Message: Re: Replace IN VALUES with ANY in WHERE clauses during optimization
diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c
index 08c4648f936..7c1b2f4cfe6 100644
--- a/src/backend/optimizer/plan/subselect.c
+++ b/src/backend/optimizer/plan/subselect.c
@@ -1215,8 +1215,8 @@ inline_cte_walker(Node *node, inline_cte_walker_context *context)
 }
 
 /*
- * The function traverses the tree looking for elements of type var.
- * If it finds it, it returns true.
+ * The function traverses the tree looking for subqueries particularly
+ * elements of type RangeTblEntry. If it finds it, it returns true.
  */
 static bool
 values_simplicity_check_walker(Node *node, void *ctx)
@@ -1225,7 +1225,7 @@ values_simplicity_check_walker(Node *node, void *ctx)
 	{
 		return false;
 	}
-	else if(IsA(node, Var))
+	else if(IsA(node, RangeTblEntry))
 		return true;
 	else if(IsA(node, Query))
 		return query_tree_walker((Query *) node,
@@ -1302,6 +1302,22 @@ convert_VALUES_to_ANY(Query *query, Node *testexpr)
 		List *elem = lfirst(lc);
 		Node *value = linitial(elem);
 
+		if(IsA(value, Var))
+		{
+			/*
+			 * We don't risk optimizing if the var is volatile, either.
+			 */
+			if(contain_volatile_functions(value))
+				return NULL;
+
+			/*
+			 * Upper-level vars will now be one level closer to their
+			 * parent than before; in particular, anything that had been level 1
+			 * becomes level zero.
+			*/
+			IncrementVarSublevelsUp(value, -1, 1);
+		}
+
 		value = eval_const_expressions(NULL, value);
 
 		if (!IsA(value, Const))
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index 5138a00349c..63e0114f177 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -3095,3 +3095,14 @@ SELECT ten FROM onek t WHERE 1.0 IN (VALUES (1), (3));
      ->  Values Scan on "*VALUES*"
 (5 rows)
 
+EXPLAIN (COSTS OFF)
+SELECT * FROM onek t1, lateral (SELECT * FROM onek t2 WHERE t2.ten IN (values (t1.ten), (1)));
+                    QUERY PLAN                    
+--------------------------------------------------
+ Nested Loop
+   Join Filter: (t2.ten = ANY (ARRAY[t1.ten, 1]))
+   ->  Seq Scan on onek t1
+   ->  Materialize
+         ->  Seq Scan on onek t2
+(5 rows)
+
diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql
index 480f8d7b852..088619f0ffc 100644
--- a/src/test/regress/sql/subselect.sql
+++ b/src/test/regress/sql/subselect.sql
@@ -1357,3 +1357,6 @@ SELECT ten FROM onek t WHERE 1.0 IN ((VALUES (1), (3))::integer);
 
 EXPLAIN (COSTS OFF)
 SELECT ten FROM onek t WHERE 1.0 IN (VALUES (1), (3));
+
+EXPLAIN (COSTS OFF)
+SELECT * FROM onek t1, lateral (SELECT * FROM onek t2 WHERE t2.ten IN (values (t1.ten), (1)));