Skip to content

Commit

Permalink
Fix explain(locus) show NULL. (#238)
Browse files Browse the repository at this point in the history
Fix materialize locus is null when enable_material is off.
When creating plan, make_material() is added directly besides
a material path and lacks of locus info.
Add locus info for that material plan.

Fix locus is null under Subplan.
fix_subplan_motion() will add Motion by Flow, either Gather or
Broadcast. Add locus according to Flow type.

Fix Result, One-Time Filter Result locus is null.
Result node will call create_scan_plan() itself if it's a simple
RTE_RESULT base relation. Add locus for that.

Fix PREPARE EXECUTE statement locus null.
Plancache will copy PlannedStmt list if it's not a oneshot plan.
Add files locustype and parallel in CopyPlanFields().

Authored-by: Zhang Mingli avamingli@gmail.com
  • Loading branch information
avamingli authored and baotingfang committed Dec 1, 2023
1 parent 235aff9 commit 657ff08
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/backend/cdb/cdbllize.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions src/backend/nodes/copyfuncs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
8 changes: 7 additions & 1 deletion src/backend/optimizer/plan/createplan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -7808,6 +7810,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;

Expand Down Expand Up @@ -8285,6 +8289,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;
Expand Down
156 changes: 156 additions & 0 deletions src/test/regress/expected/gp_parallel.out
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
47 changes: 47 additions & 0 deletions src/test/regress/sql/gp_parallel.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 657ff08

Please sign in to comment.