diff --git a/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp b/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp index 83cda2c1162b..ca4ac97176f1 100644 --- a/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp +++ b/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp @@ -509,7 +509,7 @@ - + @@ -529,7 +529,7 @@ - + @@ -564,115 +564,115 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -680,118 +680,118 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -799,94 +799,94 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -894,70 +894,70 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -965,36 +965,36 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -1002,44 +1002,44 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - + + + + + + + + + + @@ -1049,45 +1049,45 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -1095,38 +1095,38 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -1155,54 +1155,54 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - + + + + + + + + + + + @@ -1214,36 +1214,36 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -1251,44 +1251,44 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - + + + + + + + + + + @@ -1299,36 +1299,36 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -1336,44 +1336,44 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - + + + + + + + + + + @@ -1404,13 +1404,13 @@ - + - + @@ -1678,25 +1678,25 @@ - + - + - - + + - - + + @@ -1705,228 +1705,228 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -1936,7 +1936,7 @@ - + @@ -1956,7 +1956,7 @@ - + @@ -1969,226 +1969,220 @@ - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + - + - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -2196,94 +2190,91 @@ - + - + - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -2291,77 +2282,74 @@ - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + - + @@ -2370,36 +2358,36 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -2407,85 +2395,82 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - - - - - - + + + + + + + - + - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -2497,41 +2482,38 @@ - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - + + @@ -2557,57 +2539,54 @@ - + - - - - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - + + + + + + + + + + @@ -2619,36 +2598,36 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -2656,44 +2635,44 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - - - - - - + + + + + + + @@ -2704,36 +2683,36 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + @@ -2741,29 +2720,29 @@ - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + @@ -2771,14 +2750,14 @@ - - - - - - - - + + + + + + + + @@ -2806,7 +2785,7 @@ - + @@ -2841,9 +2820,6 @@ - - - @@ -2950,7 +2926,7 @@ - + @@ -2958,9 +2934,6 @@ - - - @@ -3069,7 +3042,7 @@ - + @@ -3082,8 +3055,8 @@ - - + + @@ -3092,11 +3065,8 @@ - - - - - + + @@ -3200,20 +3170,17 @@ - + - + - - - - - + + diff --git a/src/backend/gporca/libgpopt/src/operators/CLogicalDynamicGetBase.cpp b/src/backend/gporca/libgpopt/src/operators/CLogicalDynamicGetBase.cpp index e17004d5f89e..527e0b06d051 100644 --- a/src/backend/gporca/libgpopt/src/operators/CLogicalDynamicGetBase.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CLogicalDynamicGetBase.cpp @@ -180,7 +180,18 @@ CLogicalDynamicGetBase::DeriveOutputColumns(CMemoryPool *mp, ) { CColRefSet *pcrs = GPOS_NEW(mp) CColRefSet(mp); - pcrs->Include(m_pdrgpcrOutput); + for (ULONG i = 0; i < m_pdrgpcrOutput->Size(); i++) + { + // We want to limit the output columns to only those which are referenced in the query + // We will know the entire list of columns which are referenced in the query only after + // translating the entire DXL to an expression. Hence we should not limit the output columns + // before we have processed the entire DXL. + if ((*m_pdrgpcrOutput)[i]->GetUsage() == CColRef::EUsed || + (*m_pdrgpcrOutput)[i]->GetUsage() == CColRef::EUnknown) + { + pcrs->Include((*m_pdrgpcrOutput)[i]); + } + } return pcrs; } diff --git a/src/test/regress/expected/qp_correlated_query.out b/src/test/regress/expected/qp_correlated_query.out index 29abfe03fd53..1a3d4777b120 100644 --- a/src/test/regress/expected/qp_correlated_query.out +++ b/src/test/regress/expected/qp_correlated_query.out @@ -3910,6 +3910,113 @@ DROP TABLE skip_correlated_t3; DROP TABLE skip_correlated_t4; reset optimizer_join_order; reset optimizer_trace_fallback; +-------------------------------------------------------------------------------- +-- Ensure ORCA generates the correct plan with the exists clause +-- for the partitioned table. +-------------------------------------------------------------------------------- +CREATE TABLE offers ( + id int, + product int, + date date +) DISTRIBUTED BY (id); +INSERT INTO offers SELECT i, i, '2023-01-01'::date + (i||' min')::interval FROM generate_series(1, 1000) i; +CREATE TABLE contacts ( + contact int, + id int, + date date +) DISTRIBUTED BY (id) PARTITION BY RANGE(date) (START (date '2023-01-01') INCLUSIVE END (date '2023-02-01') EXCLUSIVE EVERY (INTERVAL '1 month')); +NOTICE: CREATE TABLE will create partition "contacts_1_prt_1" for table "contacts" +INSERT INTO contacts SELECT i, i, '2023-01-01'::date + (i||' min')::interval FROM generate_series(1, 1000) i; +SET optimizer_enforce_subplans = on; +EXPLAIN (COSTS off, VERBOSE on) +SELECT id FROM offers WHERE EXISTS ( + SELECT id FROM contacts WHERE id = 1 +); + QUERY PLAN +---------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: offers.id + -> Result + Output: offers.id + One-Time Filter: $0 + InitPlan 1 (returns $0) (slice3) + -> Limit + Output: contacts_1_prt_1.id + -> Gather Motion 1:1 (slice1; segments: 1) + Output: contacts_1_prt_1.id + -> Limit + Output: contacts_1_prt_1.id + -> Append + -> Seq Scan on qp_correlated_query.contacts_1_prt_1 + Output: contacts_1_prt_1.id + Filter: (contacts_1_prt_1.id = 1) + -> Seq Scan on qp_correlated_query.offers + Output: offers.id, offers.product, offers.date + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +CREATE INDEX ON contacts USING bitmap(id); +EXPLAIN (COSTS off, VERBOSE on) +SELECT id FROM offers WHERE EXISTS ( + SELECT id FROM contacts WHERE id = 1 +); + QUERY PLAN +---------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: offers.id + -> Result + Output: offers.id + One-Time Filter: $0 + InitPlan 1 (returns $0) (slice3) + -> Limit + Output: contacts_1_prt_1.id + -> Gather Motion 1:1 (slice1; segments: 1) + Output: contacts_1_prt_1.id + -> Limit + Output: contacts_1_prt_1.id + -> Append + -> Seq Scan on qp_correlated_query.contacts_1_prt_1 + Output: contacts_1_prt_1.id + Filter: (contacts_1_prt_1.id = 1) + -> Seq Scan on qp_correlated_query.offers + Output: offers.id, offers.product, offers.date + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +CREATE INDEX ON contacts USING btree(id); +EXPLAIN (COSTS off, VERBOSE on) +SELECT id FROM offers WHERE EXISTS ( + SELECT id FROM contacts WHERE id = 1 +); + QUERY PLAN +---------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: offers.id + -> Result + Output: offers.id + One-Time Filter: $0 + InitPlan 1 (returns $0) (slice3) + -> Limit + Output: contacts_1_prt_1.id + -> Gather Motion 1:1 (slice1; segments: 1) + Output: contacts_1_prt_1.id + -> Limit + Output: contacts_1_prt_1.id + -> Append + -> Seq Scan on qp_correlated_query.contacts_1_prt_1 + Output: contacts_1_prt_1.id + Filter: (contacts_1_prt_1.id = 1) + -> Seq Scan on qp_correlated_query.offers + Output: offers.id, offers.product, offers.date + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +RESET optimizer_enforce_subplans; +DROP TABLE offers; +DROP TABLE contacts; -- ---------------------------------------------------------------------- -- Test: teardown.sql -- ---------------------------------------------------------------------- diff --git a/src/test/regress/expected/qp_correlated_query_optimizer.out b/src/test/regress/expected/qp_correlated_query_optimizer.out index c45a9b1759bf..4f81fe45bb50 100644 --- a/src/test/regress/expected/qp_correlated_query_optimizer.out +++ b/src/test/regress/expected/qp_correlated_query_optimizer.out @@ -4050,6 +4050,124 @@ DROP TABLE skip_correlated_t3; DROP TABLE skip_correlated_t4; reset optimizer_join_order; reset optimizer_trace_fallback; +-------------------------------------------------------------------------------- +-- Ensure ORCA generates the correct plan with the exists clause +-- for the partitioned table. +-------------------------------------------------------------------------------- +CREATE TABLE offers ( + id int, + product int, + date date +) DISTRIBUTED BY (id); +INSERT INTO offers SELECT i, i, '2023-01-01'::date + (i||' min')::interval FROM generate_series(1, 1000) i; +CREATE TABLE contacts ( + contact int, + id int, + date date +) DISTRIBUTED BY (id) PARTITION BY RANGE(date) (START (date '2023-01-01') INCLUSIVE END (date '2023-02-01') EXCLUSIVE EVERY (INTERVAL '1 month')); +NOTICE: CREATE TABLE will create partition "contacts_1_prt_1" for table "contacts" +INSERT INTO contacts SELECT i, i, '2023-01-01'::date + (i||' min')::interval FROM generate_series(1, 1000) i; +SET optimizer_enforce_subplans = on; +EXPLAIN (COSTS off, VERBOSE on) +SELECT id FROM offers WHERE EXISTS ( + SELECT id FROM contacts WHERE id = 1 +); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice3; segments: 3) + Output: offers.id + -> Seq Scan on qp_correlated_query.offers + Output: offers.id + Filter: (SubPlan 1) + SubPlan 1 (slice3; segments: 3) + -> Materialize + Output: contacts.id + -> Broadcast Motion 1:3 (slice2) + Output: contacts.id + -> Limit + Output: contacts.id + -> Gather Motion 3:1 (slice1; segments: 3) + Output: contacts.id + -> Sequence + Output: contacts.id + -> Partition Selector for contacts (dynamic scan id: 1) + Partitions selected: 1 (out of 1) + -> Dynamic Seq Scan on qp_correlated_query.contacts (dynamic scan id: 1) + Output: contacts.id + Filter: (contacts.id = 1) + Optimizer: Pivotal Optimizer (GPORCA) + Settings: optimizer=on +(23 rows) + +CREATE INDEX ON contacts USING bitmap(id); +EXPLAIN (COSTS off, VERBOSE on) +SELECT id FROM offers WHERE EXISTS ( + SELECT id FROM contacts WHERE id = 1 +); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice3; segments: 3) + Output: offers.id + -> Seq Scan on qp_correlated_query.offers + Output: offers.id + Filter: (SubPlan 1) + SubPlan 1 (slice3; segments: 3) + -> Materialize + Output: contacts.id + -> Broadcast Motion 1:3 (slice2) + Output: contacts.id + -> Limit + Output: contacts.id + -> Gather Motion 3:1 (slice1; segments: 3) + Output: contacts.id + -> Sequence + Output: contacts.id + -> Partition Selector for contacts (dynamic scan id: 1) + Partitions selected: 1 (out of 1) + -> Dynamic Bitmap Heap Scan on qp_correlated_query.contacts (dynamic scan id: 1) + Output: contacts.id + Recheck Cond: (contacts.id = 1) + -> Dynamic Bitmap Index Scan on contacts_id_idx + Index Cond: (contacts.id = 1) + Optimizer: Pivotal Optimizer (GPORCA) + Settings: optimizer=on +(25 rows) + +CREATE INDEX ON contacts USING btree(id); +EXPLAIN (COSTS off, VERBOSE on) +SELECT id FROM offers WHERE EXISTS ( + SELECT id FROM contacts WHERE id = 1 +); + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice3; segments: 3) + Output: offers.id + -> Seq Scan on qp_correlated_query.offers + Output: offers.id + Filter: (SubPlan 1) + SubPlan 1 (slice3; segments: 3) + -> Materialize + Output: contacts.id + -> Broadcast Motion 1:3 (slice2) + Output: contacts.id + -> Limit + Output: contacts.id + -> Gather Motion 3:1 (slice1; segments: 3) + Output: contacts.id + -> Sequence + Output: contacts.id + -> Partition Selector for contacts (dynamic scan id: 1) + Partitions selected: 1 (out of 1) + -> Dynamic Index Scan on qp_correlated_query.contacts (dynamic scan id: 1) + Output: contacts.id + Index Cond: (contacts.id = 1) + Optimizer: Pivotal Optimizer (GPORCA) + Settings: optimizer=on +(23 rows) + +RESET optimizer_enforce_subplans; +DROP TABLE offers; +DROP TABLE contacts; -- ---------------------------------------------------------------------- -- Test: teardown.sql -- ---------------------------------------------------------------------- diff --git a/src/test/regress/sql/qp_correlated_query.sql b/src/test/regress/sql/qp_correlated_query.sql index 1bead6cefa34..b32528153583 100644 --- a/src/test/regress/sql/qp_correlated_query.sql +++ b/src/test/regress/sql/qp_correlated_query.sql @@ -834,6 +834,40 @@ DROP TABLE skip_correlated_t4; reset optimizer_join_order; reset optimizer_trace_fallback; +-------------------------------------------------------------------------------- +-- Ensure ORCA generates the correct plan with the exists clause +-- for the partitioned table. +-------------------------------------------------------------------------------- +CREATE TABLE offers ( + id int, + product int, + date date +) DISTRIBUTED BY (id); +INSERT INTO offers SELECT i, i, '2023-01-01'::date + (i||' min')::interval FROM generate_series(1, 1000) i; +CREATE TABLE contacts ( + contact int, + id int, + date date +) DISTRIBUTED BY (id) PARTITION BY RANGE(date) (START (date '2023-01-01') INCLUSIVE END (date '2023-02-01') EXCLUSIVE EVERY (INTERVAL '1 month')); +INSERT INTO contacts SELECT i, i, '2023-01-01'::date + (i||' min')::interval FROM generate_series(1, 1000) i; +SET optimizer_enforce_subplans = on; +EXPLAIN (COSTS off, VERBOSE on) +SELECT id FROM offers WHERE EXISTS ( + SELECT id FROM contacts WHERE id = 1 +); +CREATE INDEX ON contacts USING bitmap(id); +EXPLAIN (COSTS off, VERBOSE on) +SELECT id FROM offers WHERE EXISTS ( + SELECT id FROM contacts WHERE id = 1 +); +CREATE INDEX ON contacts USING btree(id); +EXPLAIN (COSTS off, VERBOSE on) +SELECT id FROM offers WHERE EXISTS ( + SELECT id FROM contacts WHERE id = 1 +); +RESET optimizer_enforce_subplans; +DROP TABLE offers; +DROP TABLE contacts; -- ---------------------------------------------------------------------- -- Test: teardown.sql -- ----------------------------------------------------------------------