diff --git a/src/backend/gpopt/translate/CTranslatorDXLToScalar.cpp b/src/backend/gpopt/translate/CTranslatorDXLToScalar.cpp index 00bb723e543b..c53e785fcd50 100644 --- a/src/backend/gpopt/translate/CTranslatorDXLToScalar.cpp +++ b/src/backend/gpopt/translate/CTranslatorDXLToScalar.cpp @@ -751,6 +751,8 @@ CTranslatorDXLToScalar::TranslateDXLScalarSubplanToScalar( // Generate var mapping to handle test expression based on the required // output context. Test expression may contain vars from external // (relative to subplan) nodes, so add their context too. + // We create a copy of the external mapping because we don't want to + // add TestExpr params to the original. CMappingColIdVarPlStmt test_expr_var_mapping = CMappingColIdVarPlStmt( m_mp, m_base_table_context, outer_child_contexts, &test_expr_output_ctxt, plstmt->GetDXLToPlStmtContext()); @@ -762,7 +764,6 @@ CTranslatorDXLToScalar::TranslateDXLScalarSubplanToScalar( dxlop->GetDxlTestExpr(), slink, &test_expr_var_mapping); const CDXLColRefArray *outer_refs = dxlop->GetDxlOuterColRefsArray(); - const ULONG len = outer_refs->Size(); // Translate a copy of the translate context: the param mappings from the outer scope get copied in the constructor diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out index db6b4180f76b..42d0265aa04e 100755 --- a/src/test/regress/expected/subselect.out +++ b/src/test/regress/expected/subselect.out @@ -1161,9 +1161,9 @@ drop table tl3; drop table tl4; -- Check deep tree support in Test expression node when outer params are present with =ANY or IN queries CREATE TABLE test_tbl_t (text_t text, int_t int) DISTRIBUTED BY (int_t); -INSERT INTO test_tbl_t VALUES ('0', 0), ('0', 1); +INSERT INTO test_tbl_t VALUES ('0', 0); CREATE TABLE test_tbl_d (text_d text, int_d int) DISTRIBUTED BY (int_d); -INSERT INTO test_tbl_d VALUES ('0', 0), ('0', 1); +INSERT INTO test_tbl_d VALUES ('0', 0); CREATE TABLE test_tbl_p (text_p text, int_p int) DISTRIBUTED BY (int_p); INSERT INTO test_tbl_p VALUES ('0', 0), ('0', 1); EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM test_tbl_t WHERE @@ -1202,6 +1202,53 @@ EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM test_tbl_t WHERE Settings: optimizer=off (30 rows) +SELECT * FROM test_tbl_t WHERE + (int_t IN (SELECT int_d FROM test_tbl_d)) IN (SELECT int_p = 1 from test_tbl_p) ORDER BY int_t; + text_t | int_t +--------+------- + 0 | 0 +(1 row) + +INSERT INTO test_tbl_t VALUES ('0', 1); +INSERT INTO test_tbl_d VALUES ('0', 1); +INSERT INTO test_tbl_p VALUES ('0', 0); +ANALYZE test_tbl_t; +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM test_tbl_t WHERE + (int_t IN (SELECT int_d FROM test_tbl_d)) IN (SELECT int_p = 1 from test_tbl_p) ORDER BY int_t; + QUERY PLAN +------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice4; segments: 3) + Output: test_tbl_t.text_t, test_tbl_t.int_t + Merge Key: test_tbl_t.int_t + -> Sort + Output: test_tbl_t.text_t, test_tbl_t.int_t + Sort Key: test_tbl_t.int_t + -> Hash Semi Join + Output: test_tbl_t.text_t, test_tbl_t.int_t + Hash Cond: (((hashed SubPlan 1)) = (test_tbl_p.int_p = 1)) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Output: test_tbl_t.text_t, test_tbl_t.int_t, ((hashed SubPlan 1)) + Hash Key: ((hashed SubPlan 1)) + -> Seq Scan on public.test_tbl_t + Output: test_tbl_t.text_t, test_tbl_t.int_t, (hashed SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Materialize + Output: test_tbl_d.int_d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: test_tbl_d.int_d + -> Seq Scan on public.test_tbl_d + Output: test_tbl_d.int_d + -> Hash + Output: test_tbl_p.int_p + -> Redistribute Motion 3:3 (slice3; segments: 3) + Output: test_tbl_p.int_p + Hash Key: (test_tbl_p.int_p = 1) + -> Seq Scan on public.test_tbl_p + Output: test_tbl_p.int_p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(30 rows) + SELECT * FROM test_tbl_t WHERE (int_t IN (SELECT int_d FROM test_tbl_d)) IN (SELECT int_p = 1 from test_tbl_p) ORDER BY int_t; text_t | int_t diff --git a/src/test/regress/expected/subselect_optimizer.out b/src/test/regress/expected/subselect_optimizer.out index eab3f06cf612..e1fddefb3fb9 100644 --- a/src/test/regress/expected/subselect_optimizer.out +++ b/src/test/regress/expected/subselect_optimizer.out @@ -1237,11 +1237,73 @@ drop table tl3; drop table tl4; -- Check deep tree support in Test expression node when outer params are present with =ANY or IN queries CREATE TABLE test_tbl_t (text_t text, int_t int) DISTRIBUTED BY (int_t); -INSERT INTO test_tbl_t VALUES ('0', 0), ('0', 1); +INSERT INTO test_tbl_t VALUES ('0', 0); CREATE TABLE test_tbl_d (text_d text, int_d int) DISTRIBUTED BY (int_d); -INSERT INTO test_tbl_d VALUES ('0', 0), ('0', 1); +INSERT INTO test_tbl_d VALUES ('0', 0); CREATE TABLE test_tbl_p (text_p text, int_p int) DISTRIBUTED BY (int_p); INSERT INTO test_tbl_p VALUES ('0', 0), ('0', 1); +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM test_tbl_t WHERE + (int_t IN (SELECT int_d FROM test_tbl_d)) IN (SELECT int_p = 1 from test_tbl_p) ORDER BY int_t; + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Result + Output: test_tbl_t.text_t, test_tbl_t.int_t + Filter: (SubPlan 1) + -> Sort + Output: test_tbl_t.text_t, test_tbl_t.int_t + Sort Key: test_tbl_t.int_t + -> Gather Motion 3:1 (slice1; segments: 3) + Output: test_tbl_t.text_t, test_tbl_t.int_t + -> Seq Scan on public.test_tbl_t + Output: test_tbl_t.text_t, test_tbl_t.int_t + SubPlan 1 (slice0) + -> Result + Output: (count("outer".ColRef_0028)), (sum((CASE WHEN ((test_tbl_t.int_t = test_tbl_d.int_d) IS NULL) THEN 1 ELSE 0 END))), ((test_tbl_p.int_p = 1)) + -> GroupAggregate + Output: count("outer".ColRef_0028), sum((CASE WHEN ((test_tbl_t.int_t = test_tbl_d.int_d) IS NULL) THEN 1 ELSE 0 END)), ((test_tbl_p.int_p = 1)), test_tbl_p.int_p, test_tbl_p.ctid, test_tbl_p.gp_segment_id + Group Key: test_tbl_p.int_p, test_tbl_p.ctid, test_tbl_p.gp_segment_id, ((test_tbl_p.int_p = 1)) + -> Sort + Output: ((test_tbl_p.int_p = 1)), (CASE WHEN ((test_tbl_t.int_t = test_tbl_d.int_d) IS NULL) THEN 1 ELSE 0 END), test_tbl_p.int_p, test_tbl_p.ctid, test_tbl_p.gp_segment_id, "outer".ColRef_0028 + Sort Key: test_tbl_p.int_p, test_tbl_p.ctid, test_tbl_p.gp_segment_id, ((test_tbl_p.int_p = 1)) + -> Result + Output: (test_tbl_p.int_p = 1), CASE WHEN ((test_tbl_t.int_t = test_tbl_d.int_d) IS NULL) THEN 1 ELSE 0 END, test_tbl_p.int_p, test_tbl_p.ctid, test_tbl_p.gp_segment_id, "outer".ColRef_0028 + -> Nested Loop Left Join + Output: test_tbl_p.int_p, test_tbl_p.ctid, test_tbl_p.gp_segment_id, test_tbl_d.int_d, "outer".ColRef_0028 + Join Filter: true + -> Materialize + Output: test_tbl_p.int_p, test_tbl_p.ctid, test_tbl_p.gp_segment_id + -> Gather Motion 3:1 (slice3; segments: 3) + Output: test_tbl_p.int_p, test_tbl_p.ctid, test_tbl_p.gp_segment_id + -> Seq Scan on public.test_tbl_p + Output: test_tbl_p.int_p, test_tbl_p.ctid, test_tbl_p.gp_segment_id + -> Materialize + Output: "outer".ColRef_0028, test_tbl_d.int_d + -> Result + Output: true, test_tbl_d.int_d + -> Result + Output: test_tbl_d.int_d + Filter: ((test_tbl_t.int_t = test_tbl_d.int_d) IS NOT FALSE) + -> Materialize + Output: test_tbl_d.int_d + -> Gather Motion 3:1 (slice2; segments: 3) + Output: test_tbl_d.int_d + -> Seq Scan on public.test_tbl_d + Output: test_tbl_d.int_d + Optimizer: Pivotal Optimizer (GPORCA) + Settings: optimizer=on +(45 rows) + +SELECT * FROM test_tbl_t WHERE + (int_t IN (SELECT int_d FROM test_tbl_d)) IN (SELECT int_p = 1 from test_tbl_p) ORDER BY int_t; + text_t | int_t +--------+------- + 0 | 0 +(1 row) + +INSERT INTO test_tbl_t VALUES ('0', 1); +INSERT INTO test_tbl_d VALUES ('0', 1); +INSERT INTO test_tbl_p VALUES ('0', 0); +ANALYZE test_tbl_t; EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM test_tbl_t WHERE (int_t IN (SELECT int_d FROM test_tbl_d)) IN (SELECT int_p = 1 from test_tbl_p) ORDER BY int_t; QUERY PLAN diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql index 53ccec5c4a16..df6df6ed12aa 100644 --- a/src/test/regress/sql/subselect.sql +++ b/src/test/regress/sql/subselect.sql @@ -617,14 +617,24 @@ drop table tl4; -- Check deep tree support in Test expression node when outer params are present with =ANY or IN queries CREATE TABLE test_tbl_t (text_t text, int_t int) DISTRIBUTED BY (int_t); -INSERT INTO test_tbl_t VALUES ('0', 0), ('0', 1); +INSERT INTO test_tbl_t VALUES ('0', 0); CREATE TABLE test_tbl_d (text_d text, int_d int) DISTRIBUTED BY (int_d); -INSERT INTO test_tbl_d VALUES ('0', 0), ('0', 1); +INSERT INTO test_tbl_d VALUES ('0', 0); CREATE TABLE test_tbl_p (text_p text, int_p int) DISTRIBUTED BY (int_p); INSERT INTO test_tbl_p VALUES ('0', 0), ('0', 1); +EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM test_tbl_t WHERE + (int_t IN (SELECT int_d FROM test_tbl_d)) IN (SELECT int_p = 1 from test_tbl_p) ORDER BY int_t; +SELECT * FROM test_tbl_t WHERE + (int_t IN (SELECT int_d FROM test_tbl_d)) IN (SELECT int_p = 1 from test_tbl_p) ORDER BY int_t; + +INSERT INTO test_tbl_t VALUES ('0', 1); +INSERT INTO test_tbl_d VALUES ('0', 1); +INSERT INTO test_tbl_p VALUES ('0', 0); +ANALYZE test_tbl_t; + EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM test_tbl_t WHERE (int_t IN (SELECT int_d FROM test_tbl_d)) IN (SELECT int_p = 1 from test_tbl_p) ORDER BY int_t; SELECT * FROM test_tbl_t WHERE