From eae0e20deffb0a73f7cb0e94746f94a1347e71b1 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 31 Jan 2023 11:57:47 -0500 Subject: [PATCH] Remove over-optimistic Assert. In commit 2489d76c4, I'd thought it'd be safe to assert that a PlaceHolderVar appearing in a scan-level expression has empty nullingrels. However this is not so, as when we determine that a join relation is certainly empty we'll put its targetlist into a Result-with-constant-false-qual node, and nothing is done to adjust the nullingrels of the Vars or PHVs therein. (Arguably, a Result used in this way isn't really a scan-level node, but it certainly isn't an upper node either ...) It's not clear this is worth any close analysis, so let's just take out the faulty Assert. Per report from Robins Tharakan. I added a test case based on his example, just in case somebody tries to tighten this up. Discussion: https://postgr.es/m/CAEP4nAz7Enq3+DEthGG7j27DpuwSRZnW0Nh6jtNh75yErQ_nbA@mail.gmail.com --- src/backend/optimizer/plan/setrefs.c | 2 +- src/test/regress/expected/join.out | 14 ++++++++++++++ src/test/regress/sql/join.sql | 8 ++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c index 4348bfef601..186fc8014b6 100644 --- a/src/backend/optimizer/plan/setrefs.c +++ b/src/backend/optimizer/plan/setrefs.c @@ -2205,7 +2205,7 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context) /* At scan level, we should always just evaluate the contained expr */ PlaceHolderVar *phv = (PlaceHolderVar *) node; - Assert(phv->phnullingrels == NULL); + /* XXX can we assert something about phnullingrels? */ return fix_scan_expr_mutator((Node *) phv->phexpr, context); } if (IsA(node, AlternativeSubPlan)) diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out index 87e12768042..e73ba93ca3c 100644 --- a/src/test/regress/expected/join.out +++ b/src/test/regress/expected/join.out @@ -3599,6 +3599,20 @@ where f1 in ( select c3.f1 from ctetable c2 full join ctetable c3 on true ); 1 (1 row) +-- Test PHV that winds up in a Result node, despite having nonempty nullingrels +explain (verbose, costs off) +select table_catalog, table_name +from int4_tbl t1 + inner join (int8_tbl t2 + left join information_schema.column_udt_usage on null) + on null; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Result + Output: (current_database())::information_schema.sql_identifier, (c.relname)::information_schema.sql_identifier + One-Time Filter: false +(3 rows) + -- -- test inlining of immutable functions -- diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql index 2bb24dbfcdc..ed26ffd8a86 100644 --- a/src/test/regress/sql/join.sql +++ b/src/test/regress/sql/join.sql @@ -1181,6 +1181,14 @@ with ctetable as not materialized ( select 1 as f1 ) select * from ctetable c1 where f1 in ( select c3.f1 from ctetable c2 full join ctetable c3 on true ); +-- Test PHV that winds up in a Result node, despite having nonempty nullingrels +explain (verbose, costs off) +select table_catalog, table_name +from int4_tbl t1 + inner join (int8_tbl t2 + left join information_schema.column_udt_usage on null) + on null; + -- -- test inlining of immutable functions --