diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index d3c23e0bfe34931f7a82002a460e93b4b4a08603..fb4c45f592e5310c8f117c5ae8028d02e4a03d53 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -933,9 +933,22 @@ show_dispatch_info(Slice *slice, ExplainState *es, Plan *plan) fplan = fplan->lefttree; Assert(!IsA(fplan, Motion)); - Assert(fplan->flow); - - if (fplan->flow->flotype == FLOW_SINGLETON) + if (!fplan->flow) + { + /* + * This shouldn't happen, but just in case the planner + * failed to decorate a node with a flow, don't panic + * in production. Not all nodes need to be marked with a + * flow, as long as the Motions, and the nodes immediately + * below a Motion are, so this just leads to incorrect + * information in EXPLAIN output. We'd still like to fix + * such cases, though so Assert so that we catch them + * during development. + */ + Assert(fplan->flow); + segments = 1; + } + else if (fplan->flow->flotype == FLOW_SINGLETON) segments = 1; else segments = fplan->flow->numsegments; diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 028d68373514c86d14978e01ec22a6d2b8a80371..701c3dfa51ae754c01f6b6ca2a97112004de437e 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -2509,6 +2509,13 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, plan->plan_rows = clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples); plan->plan_width = 0; /* meaningless */ + + /* decorate the node with a Flow node, for EXPLAIN. */ + plan->flow = cdbpathtoplan_create_flow(root, + ipath->path.locus, + ipath->path.parent->relids, + plan); + *qual = get_actual_clauses(ipath->indexclauses); *indexqual = get_actual_clauses(ipath->indexquals); foreach(l, ipath->indexinfo->indpred) diff --git a/src/test/regress/expected/explain_format.out b/src/test/regress/expected/explain_format.out index 4a5e1e92d9eabd5edc744d2aa6d2557d5878418d..d2361afd0090a3ef1cb13b32d0b5791ac7d7f83c 100644 --- a/src/test/regress/expected/explain_format.out +++ b/src/test/regress/expected/explain_format.out @@ -627,6 +627,55 @@ QUERY PLAN } ] (1 row) +-- Test for similar bug of missing flow with bitmap index scan. +-- (github issue #9404). +CREATE INDEX ss_f1 on SUBSELECT_TBL(f1); +begin; +set local enable_seqscan=off; +set local enable_indexscan=off; +set local enable_bitmapscan=on; +explain (format json, costs off) select * from subselect_tbl where f1 < 10; +QUERY PLAN +[ + { + "Plan": { + "Node Type": "Gather Motion", + "Senders": 3, + "Receivers": 1, + "Slice": 1, + "Segments": 3, + "Gang Type": "primary reader", + "Plans": [ + { + "Node Type": "Bitmap Heap Scan", + "Parent Relationship": "Outer", + "Slice": 1, + "Segments": 3, + "Gang Type": "primary reader", + "Relation Name": "subselect_tbl", + "Alias": "subselect_tbl", + "Recheck Cond": "(f1 < 10)", + "Plans": [ + { + "Node Type": "Bitmap Index Scan", + "Parent Relationship": "Outer", + "Slice": 1, + "Segments": 3, + "Gang Type": "primary reader", + "Index Name": "ss_f1", + "Index Cond": "(f1 < 10)" + } + ] + } + ] + }, + "Settings": { + "Optimizer": "Postgres query optimizer" + } + } +] +(1 row) +commit; -- Cleanup DROP TABLE boxes; DROP TABLE apples; diff --git a/src/test/regress/expected/explain_format_optimizer.out b/src/test/regress/expected/explain_format_optimizer.out index 0043fe2c9479a9bbc33b83949b6de0e12b52e37a..50690ecf1448a76d4587df3264db10ab8565a530 100644 --- a/src/test/regress/expected/explain_format_optimizer.out +++ b/src/test/regress/expected/explain_format_optimizer.out @@ -626,6 +626,46 @@ QUERY PLAN } ] (1 row) +-- Test for similar bug of missing flow with bitmap index scan. +-- (github issue #9404). +CREATE INDEX ss_f1 on SUBSELECT_TBL(f1); +begin; +set local enable_seqscan=off; +set local enable_indexscan=off; +set local enable_bitmapscan=on; +explain (format json, costs off) select * from subselect_tbl where f1 < 10; +QUERY PLAN +[ + { + "Plan": { + "Node Type": "Gather Motion", + "Senders": 3, + "Receivers": 1, + "Slice": 1, + "Segments": 3, + "Gang Type": "primary reader", + "Plans": [ + { + "Node Type": "Index Scan", + "Parent Relationship": "Outer", + "Slice": 1, + "Segments": 3, + "Gang Type": "primary reader", + "Scan Direction": "Forward", + "Index Name": "ss_f1", + "Relation Name": "subselect_tbl", + "Alias": "subselect_tbl", + "Index Cond": "(f1 < 10)" + } + ] + }, + "Settings": { + "Optimizer": "Pivotal Optimizer (GPORCA) version 3.87.0" + } + } +] +(1 row) +commit; -- Cleanup DROP TABLE boxes; DROP TABLE apples; diff --git a/src/test/regress/sql/explain_format.sql b/src/test/regress/sql/explain_format.sql index 2b324dbd9527eef4be764da2eae1c542eee9da58..3170c86025024729b65f6233d0bdee659dc73f84 100644 --- a/src/test/regress/sql/explain_format.sql +++ b/src/test/regress/sql/explain_format.sql @@ -111,6 +111,16 @@ explain (format json) SELECT '' AS six, f1 AS "Uncorrelated Field" FROM SUBSELEC WHERE f1 IN (SELECT f2 FROM SUBSELECT_TBL WHERE f2 IN (SELECT f1 FROM SUBSELECT_TBL)); +-- Test for similar bug of missing flow with bitmap index scan. +-- (github issue #9404). +CREATE INDEX ss_f1 on SUBSELECT_TBL(f1); +begin; +set local enable_seqscan=off; +set local enable_indexscan=off; +set local enable_bitmapscan=on; +explain (format json, costs off) select * from subselect_tbl where f1 < 10; +commit; + -- Cleanup DROP TABLE boxes; DROP TABLE apples;