aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/planner.c32
-rw-r--r--src/test/regress/expected/subselect.out14
-rw-r--r--src/test/regress/sql/subselect.sql18
3 files changed, 59 insertions, 5 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index ecdd7280eb8..d58635c887c 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -777,6 +777,27 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
}
/*
+ * Now that we are done preprocessing expressions, and in particular done
+ * flattening join alias variables, get rid of the joinaliasvars lists.
+ * They no longer match what expressions in the rest of the tree look
+ * like, because we have not preprocessed expressions in those lists (and
+ * do not want to; for example, expanding a SubLink there would result in
+ * a useless unreferenced subplan). Leaving them in place simply creates
+ * a hazard for later scans of the tree. We could try to prevent that by
+ * using QTW_IGNORE_JOINALIASES in every tree scan done after this point,
+ * but that doesn't sound very reliable.
+ */
+ if (root->hasJoinRTEs)
+ {
+ foreach(l, parse->rtable)
+ {
+ RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
+
+ rte->joinaliasvars = NIL;
+ }
+ }
+
+ /*
* In some cases we may want to transfer a HAVING clause into WHERE. We
* cannot do so if the HAVING clause contains aggregates (obviously) or
* volatile functions (since a HAVING clause is supposed to be executed
@@ -902,11 +923,12 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
/*
* If the query has any join RTEs, replace join alias variables with
- * base-relation variables. We must do this before sublink processing,
- * else sublinks expanded out from join aliases would not get processed.
- * We can skip it in non-lateral RTE functions, VALUES lists, and
- * TABLESAMPLE clauses, however, since they can't contain any Vars of the
- * current query level.
+ * base-relation variables. We must do this first, since any expressions
+ * we may extract from the joinaliasvars lists have not been preprocessed.
+ * For example, if we did this after sublink processing, sublinks expanded
+ * out from join aliases would not get processed. But we can skip this in
+ * non-lateral RTE functions, VALUES lists, and TABLESAMPLE clauses, since
+ * they can't contain any Vars of the current query level.
*/
if (root->hasJoinRTEs &&
!(kind == EXPRKIND_RTFUNC ||
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index f3ebad58573..992d29bb860 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -679,6 +679,20 @@ with q as (select max(f1) from int4_tbl group by f1 order by f1)
(5 rows)
--
+-- Test case for sublinks pulled up into joinaliasvars lists in an
+-- inherited update/delete query
+--
+begin; -- this shouldn't delete anything, but be safe
+delete from road
+where exists (
+ select 1
+ from
+ int4_tbl cross join
+ ( select f1, array(select q1 from int8_tbl) as arr
+ from text_tbl ) ss
+ where road.name = ss.f1 );
+rollback;
+--
-- Test case for sublinks pushed down into subselects via join alias expansion
--
select
diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql
index 5ac8badabe7..0d2dd2f1d81 100644
--- a/src/test/regress/sql/subselect.sql
+++ b/src/test/regress/sql/subselect.sql
@@ -377,6 +377,24 @@ with q as (select max(f1) from int4_tbl group by f1 order by f1)
select q from q;
--
+-- Test case for sublinks pulled up into joinaliasvars lists in an
+-- inherited update/delete query
+--
+
+begin; -- this shouldn't delete anything, but be safe
+
+delete from road
+where exists (
+ select 1
+ from
+ int4_tbl cross join
+ ( select f1, array(select q1 from int8_tbl) as arr
+ from text_tbl ) ss
+ where road.name = ss.f1 );
+
+rollback;
+
+--
-- Test case for sublinks pushed down into subselects via join alias expansion
--