diff --git a/src/backend/cdb/cdbllize.c b/src/backend/cdb/cdbllize.c index 8c91e63d8be..dadc8f119f0 100644 --- a/src/backend/cdb/cdbllize.c +++ b/src/backend/cdb/cdbllize.c @@ -807,6 +807,7 @@ cdbllize_decorate_subplans_with_motions(PlannerInfo *root, Plan *plan) * and hashed SubPlans are never rescanned. */ if (IsA(subplan, Motion) && !sstate->is_initplan && + /* CBDB_PARALLEL_FIXME: enable_material && */ !sstate->useHashTable) subplan = (Plan *) make_material(subplan); } @@ -1075,6 +1076,8 @@ fix_subplan_motion(PlannerInfo *root, Plan *subplan, Flow *outer_query_flow) motion->senderSliceInfo = sendSlice; subplan = (Plan *) motion; + subplan->locustype = (motion->motionType == MOTIONTYPE_GATHER) ? + CdbLocusType_SingleQE: CdbLocusType_Replicated; } return subplan; } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index bfccb567432..3d6e22c5667 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -253,6 +253,8 @@ CopyPlanFields(const Plan *from, Plan *newnode) COPY_BITMAPSET_FIELD(extParam); COPY_BITMAPSET_FIELD(allParam); COPY_NODE_FIELD(flow); + COPY_SCALAR_FIELD(locustype); + COPY_SCALAR_FIELD(parallel); COPY_SCALAR_FIELD(operatorMemKB); } diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 4e159562ce0..4e2d6bdc891 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -872,6 +872,7 @@ create_scan_plan(PlannerInfo *root, Path *best_path, int flags) if (Gp_role == GP_ROLE_DISPATCH && root->config->gp_enable_direct_dispatch) DirectDispatchUpdateContentIdsFromPlan(root, plan); + plan->locustype = best_path->locus.locustype; /* * If there are any pseudoconstant clauses attached to this node, insert a * gating Result node that evaluates the pseudoconstants as one-time @@ -5265,7 +5266,8 @@ create_nestloop_plan(PlannerInfo *root, mat->plan.total_cost = matpath.total_cost; mat->plan.plan_rows = inner_plan->plan_rows; mat->plan.plan_width = inner_plan->plan_width; - + mat->plan.locustype = inner_plan->locustype; + mat->plan.parallel = inner_plan->parallel; inner_plan = (Plan *) mat; } @@ -7803,6 +7805,8 @@ make_material(Plan *lefttree) plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; + plan->locustype = lefttree->locustype; + plan->parallel = lefttree->parallel; node->cdb_strict = false; @@ -8280,6 +8284,8 @@ make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, plan->qual = NIL; plan->lefttree = lefttree; plan->righttree = NULL; + plan->locustype = lefttree->locustype; + plan->parallel = lefttree->parallel; node->limitOffset = limitOffset; node->limitCount = limitCount; diff --git a/src/test/regress/expected/gp_parallel.out b/src/test/regress/expected/gp_parallel.out index fc7155b4398..c23556a50aa 100644 --- a/src/test/regress/expected/gp_parallel.out +++ b/src/test/regress/expected/gp_parallel.out @@ -2019,6 +2019,7 @@ create table pagg_tab_p2 partition of pagg_tab for values in ('0005', '0006', '0 create table pagg_tab_p3 partition of pagg_tab for values in ('0009', '0010', '0011'); insert into pagg_tab select i % 20, i % 30, to_char(i % 12, 'FM0000'), i % 30 from generate_series(0, 2999) i; analyze pagg_tab; +set local enable_parallel to off; set local enable_partitionwise_aggregate to true; set local enable_partitionwise_join to true; set local enable_incremental_sort to off; @@ -2362,6 +2363,161 @@ explain(costs off) select c1 from semi_t1 where not c1 >=all (select c2 from sem Optimizer: Postgres query optimizer (13 rows) +abort; +-- +-- Test Materialize locus when enable_material is off. +-- +begin; +create table t1(id int) distributed by (id); +create index on t1(id); +insert into t1 values(generate_series(1, 100)); +analyze t1; +set enable_seqscan =off; +set enable_material =off; +explain (locus, costs off) +select * from + (select count(id) from t1 where id > 10) ss + right join (values (1),(2),(3)) v(x) on true; + QUERY PLAN +--------------------------------------------------------------------- + Nested Loop Left Join + Locus: Entry + -> Values Scan on "*VALUES*" + Locus: General + -> Materialize + Locus: Entry + -> Finalize Aggregate + Locus: Entry + -> Gather Motion 3:1 (slice1; segments: 3) + Locus: Entry + -> Partial Aggregate + Locus: Hashed + -> Index Only Scan using t1_id_idx on t1 + Locus: Hashed + Index Cond: (id > 10) + Optimizer: Postgres query optimizer +(16 rows) + +abort; +-- Subplan locus, One-time flter locus is null +begin; +drop table if exists mrs_t1; +NOTICE: table "mrs_t1" does not exist, skipping +create table mrs_t1(x int) distributed by (x); +insert into mrs_t1 select generate_series(1,20); +analyze mrs_t1; +explain(locus, costs off) select * from mrs_t1 where exists (select x from mrs_t1 where x < -1); + QUERY PLAN +-------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Locus: Entry + InitPlan 1 (returns $0) (slice2) + -> Gather Motion 3:1 (slice3; segments: 3) + Locus: Entry + -> Seq Scan on mrs_t1 mrs_t1_1 + Locus: Hashed + Filter: (x < '-1'::integer) + -> Result + Locus: Hashed + One-Time Filter: $0 + -> Seq Scan on mrs_t1 + Locus: Hashed + Optimizer: Postgres query optimizer +(14 rows) + +explain(locus, costs off) select * from mrs_t1 where exists (select x from mrs_t1 where x = 1); + QUERY PLAN +-------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Locus: Entry + InitPlan 1 (returns $0) (slice2) + -> Gather Motion 1:1 (slice3; segments: 1) + Locus: Entry + -> Seq Scan on mrs_t1 mrs_t1_1 + Locus: Hashed + Filter: (x = 1) + -> Result + Locus: Hashed + One-Time Filter: $0 + -> Seq Scan on mrs_t1 + Locus: Hashed + Optimizer: Postgres query optimizer +(14 rows) + +explain(locus, costs off) select * from mrs_t1 where x in (select x-95 from mrs_t1) or x < 5; + QUERY PLAN +----------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Locus: Entry + -> Seq Scan on mrs_t1 + Locus: Hashed + Filter: ((hashed SubPlan 1) OR (x < 5)) + SubPlan 1 + -> Broadcast Motion 3:3 (slice2; segments: 3) + Locus: Replicated + -> Seq Scan on mrs_t1 mrs_t1_1 + Locus: Hashed + Optimizer: Postgres query optimizer +(11 rows) + +explain(locus, costs off) select * from pg_class where oid in (select x-95 from mrs_t1) or oid < 5; + QUERY PLAN +---------------------------------------------------- + Seq Scan on pg_class + Locus: Entry + Filter: ((hashed SubPlan 1) OR (oid < '5'::oid)) + SubPlan 1 + -> Gather Motion 3:1 (slice1; segments: 3) + Locus: Entry + -> Seq Scan on mrs_t1 + Locus: Hashed + Optimizer: Postgres query optimizer +(9 rows) + +drop table if exists mrs_t1; +abort; +-- prepare, execute locus is null +begin; +create table t1(c1 int, c2 int); +analyze t1; +prepare t1_count(integer) as select count(*) from t1; +explain(locus, costs off) execute t1_count(1); + QUERY PLAN +------------------------------------------------ + Aggregate + Locus: Entry + -> Gather Motion 3:1 (slice1; segments: 3) + Locus: Entry + -> Seq Scan on t1 + Locus: Hashed + Optimizer: Postgres query optimizer +(7 rows) + +abort; +-- Result locus is null +begin; +create table t1(id int) distributed by (id); +create index on t1(id); +insert into t1 values(generate_series(1, 10)); +analyze t1; +explain(costs off, locus) select max(100) from t1; + QUERY PLAN +---------------------------------------------------------- + Result + Locus: Entry + InitPlan 1 (returns $0) (slice1) + -> Limit + Locus: Entry + -> Gather Motion 3:1 (slice2; segments: 3) + Locus: Entry + -> Result + Locus: Hashed + One-Time Filter: (100 IS NOT NULL) + -> Seq Scan on t1 + Locus: Hashed + Optimizer: Postgres query optimizer +(13 rows) + abort; -- start_ignore drop schema test_parallel cascade; diff --git a/src/test/regress/sql/gp_parallel.sql b/src/test/regress/sql/gp_parallel.sql index 2938a7dff9f..92dec58a677 100644 --- a/src/test/regress/sql/gp_parallel.sql +++ b/src/test/regress/sql/gp_parallel.sql @@ -654,6 +654,7 @@ create table pagg_tab_p2 partition of pagg_tab for values in ('0005', '0006', '0 create table pagg_tab_p3 partition of pagg_tab for values in ('0009', '0010', '0011'); insert into pagg_tab select i % 20, i % 30, to_char(i % 12, 'FM0000'), i % 30 from generate_series(0, 2999) i; analyze pagg_tab; +set local enable_parallel to off; set local enable_partitionwise_aggregate to true; set local enable_partitionwise_join to true; set local enable_incremental_sort to off; @@ -787,6 +788,52 @@ set local enable_nestloop = on; explain(costs off) select c1 from semi_t1 where not c1 >=all (select c2 from semi_t2 where c2 = c1); abort; +-- +-- Test Materialize locus when enable_material is off. +-- +begin; +create table t1(id int) distributed by (id); +create index on t1(id); +insert into t1 values(generate_series(1, 100)); +analyze t1; +set enable_seqscan =off; +set enable_material =off; +explain (locus, costs off) +select * from + (select count(id) from t1 where id > 10) ss + right join (values (1),(2),(3)) v(x) on true; +abort; + +-- Subplan locus, One-time flter locus is null +begin; +drop table if exists mrs_t1; +create table mrs_t1(x int) distributed by (x); +insert into mrs_t1 select generate_series(1,20); +analyze mrs_t1; +explain(locus, costs off) select * from mrs_t1 where exists (select x from mrs_t1 where x < -1); +explain(locus, costs off) select * from mrs_t1 where exists (select x from mrs_t1 where x = 1); +explain(locus, costs off) select * from mrs_t1 where x in (select x-95 from mrs_t1) or x < 5; +explain(locus, costs off) select * from pg_class where oid in (select x-95 from mrs_t1) or oid < 5; +drop table if exists mrs_t1; +abort; + +-- prepare, execute locus is null +begin; +create table t1(c1 int, c2 int); +analyze t1; +prepare t1_count(integer) as select count(*) from t1; +explain(locus, costs off) execute t1_count(1); +abort; + +-- Result locus is null +begin; +create table t1(id int) distributed by (id); +create index on t1(id); +insert into t1 values(generate_series(1, 10)); +analyze t1; +explain(costs off, locus) select max(100) from t1; +abort; + -- start_ignore drop schema test_parallel cascade; -- end_ignore