diff options
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 32 | ||||
-rw-r--r-- | src/test/regress/expected/subselect.out | 14 | ||||
-rw-r--r-- | src/test/regress/sql/subselect.sql | 18 |
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 -- |