From 68e7147372da71b20906b7b68d8c73653468f5fb Mon Sep 17 00:00:00 2001 From: Zhang Mingli Date: Wed, 27 Dec 2023 16:34:51 +0800 Subject: [PATCH] [AQUMV] Correct PlannerInfo fields after rewritten. If we succeed to replace SQL with materialized view, correct PlannerInfo's stuff to new one like: simple_rte_array, simple_rel_array and etc. They may be used to fetch rels after planner, for example: use physical rel's target list in create_plan(). Authored-by: Zhang Mingli avamingli@gmail.com --- src/backend/optimizer/plan/aqumv.c | 32 ++++++++++----- src/backend/optimizer/plan/planner.c | 5 +++ src/test/regress/expected/aqumv.out | 60 +++++++++++++++++++++++++++- src/test/regress/sql/aqumv.sql | 22 ++++++++++ 4 files changed, 109 insertions(+), 10 deletions(-) diff --git a/src/backend/optimizer/plan/aqumv.c b/src/backend/optimizer/plan/aqumv.c index 6279c09d2ef..5ab2e87f126 100644 --- a/src/backend/optimizer/plan/aqumv.c +++ b/src/backend/optimizer/plan/aqumv.c @@ -101,6 +101,7 @@ answer_query_using_materialized_views(PlannerInfo *root, Node *mvjtnode; int varno; RangeTblEntry *rte; + Oid origin_rel_oid; RangeTblEntry *mvrte; Relation ruleDesc; Relation matviewRel; @@ -144,11 +145,13 @@ answer_query_using_materialized_views(PlannerInfo *root, varno = ((RangeTblRef *) jtnode)->rtindex; rte = root->simple_rte_array[varno]; Assert(rte != NULL); + /* root's stuff like simple_rte_array may be changed during rewrite, fetch oid here. */ + origin_rel_oid = rte->relid; if ((rte->rtekind != RTE_RELATION) || - IsSystemClassByRelid(rte->relid) || - has_superclass(rte->relid) || - has_subclass(rte->relid)) + IsSystemClassByRelid(origin_rel_oid) || + has_superclass(origin_rel_oid) || + has_subclass(origin_rel_oid)) return mv_final_rel; ruleDesc = table_open(RewriteRelationId, AccessShareLock); @@ -235,7 +238,7 @@ answer_query_using_materialized_views(PlannerInfo *root, * AQUMV_FIXME_MVP * Must be same relation, recursiviely embeded mv is not supported now. */ - if (mvrte->relid != rte->relid) + if (mvrte->relid != origin_rel_oid) continue; /* @@ -281,11 +284,9 @@ answer_query_using_materialized_views(PlannerInfo *root, subroot->plan_params = NIL; subroot->outer_params = NULL; subroot->init_plans = NIL; - if (!parse->hasAggs) - { - subroot->agginfos = NIL; - subroot->aggtransinfos = NIL; - } + /* Agg infos would be processed by subroot itself. */ + subroot->agginfos = NIL; + subroot->aggtransinfos = NIL; subroot->parse = mvQuery; /* @@ -387,6 +388,7 @@ answer_query_using_materialized_views(PlannerInfo *root, * NB: Update processed_tlist again in case that tlist has been changed. */ preprocess_targetlist(subroot); + preprocess_aggrefs(subroot, (Node *) subroot->processed_tlist); /* * AQUMV @@ -422,6 +424,18 @@ answer_query_using_materialized_views(PlannerInfo *root, { root->parse = mvQuery; root->processed_tlist = subroot->processed_tlist; + root->agginfos = subroot->agginfos; + root->aggtransinfos = subroot->aggtransinfos; + root->simple_rte_array = subroot->simple_rte_array; + root->simple_rel_array = subroot->simple_rel_array; + root->simple_rel_array_size = subroot->simple_rel_array_size; + root->hasNonPartialAggs = subroot->hasNonPartialAggs; + root->hasNonSerialAggs = subroot->hasNonSerialAggs; + root->numOrderedAggs = subroot->numOrderedAggs; + /* CBDB specifical */ + root->hasNonCombine = subroot->hasNonCombine; + root->numPureOrderedAggs = subroot->numPureOrderedAggs; + /* * Update pathkeys which may be changed by qp_callback. * Set belows if corresponding feature is supported. diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index a1b9cc79d6f..2163d9b543a 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -561,6 +561,8 @@ standard_planner(Query *parse, const char *query_string, int cursorOptions, /* primary planning entry point (may recurse for subqueries) */ root = subquery_planner(glob, parse, NULL, false, tuple_fraction, config); + /* AQUMV: parse tree may be rewritten. */ + parse = root->parse; /* Select best Path and turn it into a Plan */ final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL); @@ -1878,7 +1880,10 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) */ if (Gp_role == GP_ROLE_DISPATCH && enable_answer_query_using_materialized_views) + { current_rel = answer_query_using_materialized_views(root, current_rel, standard_qp_callback, &qp_extra); + parse = root->parse; + } /* * Convert the query's result tlist into PathTarget format. diff --git a/src/test/regress/expected/aqumv.out b/src/test/regress/expected/aqumv.out index 1d7ba0d0c0e..0d7782963bd 100644 --- a/src/test/regress/expected/aqumv.out +++ b/src/test/regress/expected/aqumv.out @@ -351,7 +351,7 @@ select c1, c2 from aqumv_t1 where c1 < 5 and c1 > 1 and c2 = 4; explain(verbose, costs off) select c1, c2 from aqumv_t1 where c1 < 5 and c1 > 1 and c2 = 4; QUERY PLAN --------------------------------------------------------------------------- - Gather Motion 1:1 (slice1; segments: 1) + Gather Motion 3:1 (slice1; segments: 3) Output: mc1, mc2 -> Seq Scan on public.aqumv_mvt1_2 Output: mc1, mc2 @@ -985,6 +985,64 @@ select count(c2), count(*) from aqumv_t2 where c1 > 90; 10 | 11 (1 row) +abort; +-- Test Agg on IMMV who has less columns than origin table. +begin; +create table aqumv_t2(c1 int, c2 int, c3 int) distributed by (c1); +insert into aqumv_t2 select i, i+1, i+2 from generate_series(1, 100) i; +insert into aqumv_t2 values (91, NULL, 95); +analyze aqumv_t2; +create incremental materialized view aqumv_mvt2_1 as + select c3 as mc3, c1 as mc1 + from aqumv_t2 where c1 > 90; +analyze aqumv_mvt2_1; +set local enable_answer_query_using_materialized_views = off; +explain(costs off, verbose) +select count(c3) from aqumv_t2 where c1 > 90; + QUERY PLAN +----------------------------------------------------------------------------------- + Finalize Aggregate + Output: count(c3) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: (PARTIAL count(c3)) + -> Partial Aggregate + Output: PARTIAL count(c3) + -> Seq Scan on public.aqumv_t2 + Output: c1, c2, c3 + Filter: (aqumv_t2.c1 > 90) + Settings: enable_answer_query_using_materialized_views = 'off', optimizer = 'off' + Optimizer: Postgres query optimizer +(11 rows) + +select count(c3) from aqumv_t2 where c1 > 90; + count +------- + 11 +(1 row) + +set local enable_answer_query_using_materialized_views = on; +explain(costs off, verbose) +select count(c3) from aqumv_t2 where c1 > 90; + QUERY PLAN +---------------------------------------------------------------------------------- + Finalize Aggregate + Output: count(mc3) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: (PARTIAL count(mc3)) + -> Partial Aggregate + Output: PARTIAL count(mc3) + -> Seq Scan on public.aqumv_mvt2_1 + Output: mc3, mc1 + Settings: enable_answer_query_using_materialized_views = 'on', optimizer = 'off' + Optimizer: Postgres query optimizer +(10 rows) + +select count(c3) from aqumv_t2 where c1 > 90; + count +------- + 11 +(1 row) + abort; -- -- Test Group By clause of origin query. diff --git a/src/test/regress/sql/aqumv.sql b/src/test/regress/sql/aqumv.sql index 86a4de7ac9f..36200ab7ce6 100644 --- a/src/test/regress/sql/aqumv.sql +++ b/src/test/regress/sql/aqumv.sql @@ -289,6 +289,28 @@ select count(c2), count(*) from aqumv_t2 where c1 > 90; select count(c2), count(*) from aqumv_t2 where c1 > 90; abort; +-- Test Agg on IMMV who has less columns than origin table. +begin; +create table aqumv_t2(c1 int, c2 int, c3 int) distributed by (c1); +insert into aqumv_t2 select i, i+1, i+2 from generate_series(1, 100) i; +insert into aqumv_t2 values (91, NULL, 95); +analyze aqumv_t2; + +create incremental materialized view aqumv_mvt2_1 as + select c3 as mc3, c1 as mc1 + from aqumv_t2 where c1 > 90; +analyze aqumv_mvt2_1; + +set local enable_answer_query_using_materialized_views = off; +explain(costs off, verbose) +select count(c3) from aqumv_t2 where c1 > 90; +select count(c3) from aqumv_t2 where c1 > 90; +set local enable_answer_query_using_materialized_views = on; +explain(costs off, verbose) +select count(c3) from aqumv_t2 where c1 > 90; +select count(c3) from aqumv_t2 where c1 > 90; +abort; + -- -- Test Group By clause of origin query. -- GROUPING SETS