You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudberry.apache.org by yj...@apache.org on 2025/01/27 12:33:01 UTC

(cloudberry) 35/39: Fix issue https://github.com/greenplum-db/gpdb/issues/17333.

This is an automated email from the ASF dual-hosted git repository.

yjhjstz pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit f35acc7eb6c40b66e17db9df3cab2a1e6a7e7932
Author: Wenlin Zhang <zw...@vmware.com>
AuthorDate: Thu Apr 11 18:13:28 2024 +0800

    Fix issue https://github.com/greenplum-db/gpdb/issues/17333.
    
    In the adjust_setop_arguments(), if the setop is partitioned and subpath locus is general,
    it will call make_motion_hash_all_targets(), and this function will change the locus to singleQE
    when none of the columns are hashable. But mark_append_locus() will change it back to the original
    partitioned locus, which will result a wrong Motion node added in the top.
    
    This PR moves check for non-hashable column(no targetlist) to choose_setop_type().
---
 src/backend/cdb/cdbsetop.c                         | 24 +++++++++++--
 src/backend/optimizer/prep/prepunion.c             |  2 +-
 src/include/cdb/cdbsetop.h                         |  4 +--
 src/test/regress/expected/qp_union_intersect.out   | 39 ++++++++++++++++++++++
 .../expected/qp_union_intersect_optimizer.out      | 38 +++++++++++++++++++++
 src/test/regress/sql/qp_union_intersect.sql        | 10 ++++++
 6 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/src/backend/cdb/cdbsetop.c b/src/backend/cdb/cdbsetop.c
index cde90949e2..2d685e8ca6 100644
--- a/src/backend/cdb/cdbsetop.c
+++ b/src/backend/cdb/cdbsetop.c
@@ -40,13 +40,15 @@
  * See the comments in cdbsetop.h for discussion of types of setop plan.
  */
 GpSetOpType
-choose_setop_type(List *pathlist)
+choose_setop_type(List *pathlist, List *tlist_list)
 {
 	ListCell   *cell;
+	ListCell   *tlistcell;
 	bool		ok_general = true;
 	bool		ok_partitioned = true;
 	bool		ok_single_qe = true;
 	bool		has_partitioned = false;
+	bool 		all_resjunk = true;
 
 	Assert(Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_UTILITY);
 
@@ -101,9 +103,27 @@ choose_setop_type(List *pathlist)
 		}
 	}
 
+	/*
+	 * This is for handling the case when there is no targetList in the ouput.
+	 * For example: select from generate_series(1,10) except select from a;
+	 */
+	foreach(tlistcell, tlist_list)
+	{
+		List	   *subtlist = (List *) lfirst(tlistcell);
+		foreach(cell, subtlist)
+		{
+			TargetEntry *tle = (TargetEntry *) lfirst(cell);
+			if (!tle->resjunk)
+			{
+				all_resjunk = false;
+				break;
+			}
+		}
+	}
+
 	if (ok_general)
 		return PSETOP_GENERAL;
-	else if (ok_partitioned && has_partitioned)
+	else if (ok_partitioned && has_partitioned && !all_resjunk)
 		return PSETOP_PARALLEL_PARTITIONED;
 	else if (ok_single_qe)
 		return PSETOP_SEQUENTIAL_QE;
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 74725edc0b..af3e489d59 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -832,7 +832,7 @@ generate_nonunion_paths(SetOperationStmt *op, PlannerInfo *root,
 	/* CDB: Decide on approach, condition argument plans to suit. */
 	if ( Gp_role == GP_ROLE_DISPATCH )
 	{
-		optype = choose_setop_type(pathlist);
+		optype = choose_setop_type(pathlist,tlist_list);
 		adjust_setop_arguments(root, pathlist, tlist_list, optype);
 	}
 	else if ( Gp_role == GP_ROLE_UTILITY 
diff --git a/src/include/cdb/cdbsetop.h b/src/include/cdb/cdbsetop.h
index a8361e543b..de6ba3a5ec 100644
--- a/src/include/cdb/cdbsetop.h
+++ b/src/include/cdb/cdbsetop.h
@@ -39,7 +39,7 @@
  *    unordered.  The set operation is performed on the QE as if it were 
  *    sequential.
  *
- * PSETOP_SEQUENTIAL_QE
+ * PSETOP_SEQUENTIAL_OUTERQUERY
  *    Similar to SEQUENTIAL_QD/QE, but the output must be made available
  *    to the outer query's locus. We don't know the outer query's locus yet,
  *    but we treat it sequential.
@@ -59,7 +59,7 @@ typedef enum GpSetOpType
 } GpSetOpType;
 
 extern 
-GpSetOpType choose_setop_type(List *pathlist);
+GpSetOpType choose_setop_type(List *pathlist, List *tlist_list);
 
 extern
 void adjust_setop_arguments(PlannerInfo *root, List *pathlist, List *tlist_list, GpSetOpType setop_type);
diff --git a/src/test/regress/expected/qp_union_intersect.out b/src/test/regress/expected/qp_union_intersect.out
index ccc10eeca0..5b90963bb6 100644
--- a/src/test/regress/expected/qp_union_intersect.out
+++ b/src/test/regress/expected/qp_union_intersect.out
@@ -2012,6 +2012,45 @@ select * from generate_series(100, 105);
  105
 (12 rows)
 
+-- test INTERSECT/EXCEPT with General and partitioned locus, but none of the columns are hashable
+CREATE TABLE p1(a int) distributed by (a);
+INSERT INTO p1 select generate_series(1,10);
+explain (costs off)
+select from generate_series(1,5) intersect select from p1;
+                      QUERY PLAN                      
+------------------------------------------------------
+ HashSetOp Intersect
+   ->  Append
+         ->  Subquery Scan on "*SELECT* 1"
+               ->  Function Scan on generate_series
+         ->  Gather Motion 3:1  (slice1; segments: 3)
+               ->  Subquery Scan on "*SELECT* 2"
+                     ->  Seq Scan on p1
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select from generate_series(1,5) intersect select from p1;
+--
+(1 row)
+
+explain (costs off)
+select from generate_series(1,5) except select from p1;
+                      QUERY PLAN                      
+------------------------------------------------------
+ HashSetOp Except
+   ->  Append
+         ->  Subquery Scan on "*SELECT* 1"
+               ->  Function Scan on generate_series
+         ->  Gather Motion 3:1  (slice1; segments: 3)
+               ->  Subquery Scan on "*SELECT* 2"
+                     ->  Seq Scan on p1
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select from generate_series(1,5) except select from p1;
+--
+(0 rows)
+
 --
 -- Test for creation of MergeAppend paths.
 --
diff --git a/src/test/regress/expected/qp_union_intersect_optimizer.out b/src/test/regress/expected/qp_union_intersect_optimizer.out
index c312eedc99..26a8fb71c6 100644
--- a/src/test/regress/expected/qp_union_intersect_optimizer.out
+++ b/src/test/regress/expected/qp_union_intersect_optimizer.out
@@ -2014,6 +2014,44 @@ select * from generate_series(100, 105);
  105
 (12 rows)
 
+-- test INTERSECT/EXCEPT with General and partitioned locus, but none of the columns are hashable
+CREATE TABLE p1(a int) distributed by (a);
+INSERT INTO p1 select generate_series(1,10);
+explain (costs off)
+select from generate_series(1,5) intersect select from p1;
+                      QUERY PLAN                      
+------------------------------------------------------
+ Nested Loop
+   Join Filter: true
+   ->  Aggregate
+         ->  Gather Motion 3:1  (slice1; segments: 3)
+               ->  Seq Scan on p1
+   ->  Aggregate
+         ->  Function Scan on generate_series
+ Optimizer: Pivotal Optimizer (GPORCA)
+(8 rows)
+
+select from generate_series(1,5) intersect select from p1;
+--
+(1 row)
+
+explain (costs off)
+select from generate_series(1,5) except select from p1;
+                      QUERY PLAN                      
+------------------------------------------------------
+ Nested Loop Anti Join
+   Join Filter: true
+   ->  Function Scan on generate_series
+   ->  Materialize
+         ->  Gather Motion 3:1  (slice1; segments: 3)
+               ->  Seq Scan on p1
+ Optimizer: Pivotal Optimizer (GPORCA)
+(7 rows)
+
+select from generate_series(1,5) except select from p1;
+--
+(0 rows)
+
 --
 -- Test for creation of MergeAppend paths.
 --
diff --git a/src/test/regress/sql/qp_union_intersect.sql b/src/test/regress/sql/qp_union_intersect.sql
index a51759d1ba..1872734b6b 100644
--- a/src/test/regress/sql/qp_union_intersect.sql
+++ b/src/test/regress/sql/qp_union_intersect.sql
@@ -767,6 +767,16 @@ select a from t_test_append_rep
 union all
 select * from generate_series(100, 105);
 
+-- test INTERSECT/EXCEPT with General and partitioned locus, but none of the columns are hashable
+CREATE TABLE p1(a int) distributed by (a);
+INSERT INTO p1 select generate_series(1,10);
+explain (costs off)
+select from generate_series(1,5) intersect select from p1;
+select from generate_series(1,5) intersect select from p1;
+explain (costs off)
+select from generate_series(1,5) except select from p1;
+select from generate_series(1,5) except select from p1;
+
 --
 -- Test for creation of MergeAppend paths.
 --


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cloudberry.apache.org
For additional commands, e-mail: commits-help@cloudberry.apache.org