Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions src/backend/optimizer/plan/aqumv.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ answer_query_using_materialized_views(PlannerInfo *root,
(parse->rowMarks != NIL) ||
parse->hasWindowFuncs ||
parse->hasDistinctOn ||
(parse->havingQual != NULL) ||
parse->hasModifyingCTE ||
parse->sortClause ||
(parse->parentStmtType == PARENTSTMTTYPE_REFRESH_MATVIEW) ||
Expand Down Expand Up @@ -344,13 +343,19 @@ answer_query_using_materialized_views(PlannerInfo *root,
continue;

/*
* We have successfully processed target list, all columns in Aggrefs could be
* computed from mvQuery.
* It's safe to set hasAggs here.
* We have successfully processed target list, and all columns in Aggrefs
* could be computed from mvQuery.
*/
mvQuery->hasAggs = parse->hasAggs;
mvQuery->groupClause = parse->groupClause;
mvQuery->groupingSets = parse->groupingSets;
/*
* For HAVING quals have aggregations, we have already processed them in
* Aggrefs during aqumv_process_targetlist().
* For HAVING quals don't have aggregations, they may be pushed down to
* jointree's quals and would be processed in post_quals later.
*/
mvQuery->havingQual = parse->havingQual;

/*
* AQUMV
Expand All @@ -359,7 +364,6 @@ answer_query_using_materialized_views(PlannerInfo *root,
* We assume that the selection predicates of view and query expressions
* have been converted into conjunctive normal form(CNF) before we process
* them.
* AQUMV_MVP: no having quals now.
*/
preprocess_qual_conditions(subroot, (Node *) mvQuery->jointree);

Expand Down Expand Up @@ -388,7 +392,11 @@ 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);
if(mvQuery->hasAggs)
{
preprocess_aggrefs(subroot, (Node *) subroot->processed_tlist);
preprocess_aggrefs(subroot, mvQuery->havingQual);
}

/*
* AQUMV
Expand Down
145 changes: 145 additions & 0 deletions src/test/regress/expected/aqumv.out
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,151 @@ select c1, c3, count(c2) from aqumv_t3 where c1 > 90 group by cube(c1, c3);
| 95 | 1
(32 rows)

abort;
--
-- Test HAVING clause
--
begin;
create table aqumv_t4(c1 int, c2 int, c3 int) distributed by (c1);
insert into aqumv_t4 select i, i+1, i+2 from generate_series(1, 100) i;
insert into aqumv_t4 values (91, NULL, 95);
analyze aqumv_t4;
create incremental materialized view aqumv_mvt4_0 as
select c1 as mc1, c2 as mc2, c3 as mc3
from aqumv_t4 where c1 > 90;
analyze aqumv_mvt4_0;
-- HAVING clause pushed down to where quals.
set local enable_answer_query_using_materialized_views = off;
explain(costs off, verbose)
select c1, c3 from aqumv_t4 where c1 > 90 group by (c1, c3) having c3 > 97 ;
QUERY PLAN
-----------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Output: c1, c3
-> GroupAggregate
Output: c1, c3
Group Key: aqumv_t4.c1, aqumv_t4.c3
-> Sort
Output: c1, c3
Sort Key: aqumv_t4.c1, aqumv_t4.c3
-> Seq Scan on public.aqumv_t4
Output: c1, c3
Filter: ((aqumv_t4.c1 > 90) AND (aqumv_t4.c3 > 97))
Settings: enable_answer_query_using_materialized_views = 'off', optimizer = 'off'
Optimizer: Postgres query optimizer
(13 rows)

select c1, c3 from aqumv_t4 where c1 > 90 group by (c1, c3) having c3 > 97 ;
c1 | c3
-----+-----
96 | 98
100 | 102
97 | 99
99 | 101
98 | 100
(5 rows)

set local enable_answer_query_using_materialized_views = on;
explain(costs off, verbose)
select c1, c3 from aqumv_t4 where c1 > 90 group by (c1, c3) having c3 > 97 ;
QUERY PLAN
----------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Output: mc1, mc3
-> HashAggregate
Output: mc1, mc3
Group Key: aqumv_mvt4_0.mc1, aqumv_mvt4_0.mc3
-> Seq Scan on public.aqumv_mvt4_0
Output: mc1, mc2, mc3
Filter: (aqumv_mvt4_0.mc3 > 97)
Settings: enable_answer_query_using_materialized_views = 'on', optimizer = 'off'
Optimizer: Postgres query optimizer
(10 rows)

select c1, c3 from aqumv_t4 where c1 > 90 group by (c1, c3) having c3 > 97 ;
c1 | c3
-----+-----
100 | 102
96 | 98
98 | 100
99 | 101
97 | 99
(5 rows)

-- quals kept in HAVING clause.
set local enable_answer_query_using_materialized_views = off;
explain(costs off, verbose)
select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having avg(c2) > 95;
QUERY PLAN
-----------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Output: c1, c3, (avg(c2))
-> HashAggregate
Output: c1, c3, avg(c2)
Group Key: aqumv_t4.c1, aqumv_t4.c3
Filter: (avg(aqumv_t4.c2) > '95'::numeric)
-> Seq Scan on public.aqumv_t4
Output: c1, c2, c3
Filter: (aqumv_t4.c1 > 90)
Settings: enable_answer_query_using_materialized_views = 'off', optimizer = 'off'
Optimizer: Postgres query optimizer
(11 rows)

select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having avg(c2) > 95;
c1 | c3 | avg
-----+-----+----------------------
99 | 101 | 100.0000000000000000
97 | 99 | 98.0000000000000000
98 | 100 | 99.0000000000000000
95 | 97 | 96.0000000000000000
100 | 102 | 101.0000000000000000
96 | 98 | 97.0000000000000000
(6 rows)

set local enable_answer_query_using_materialized_views = on;
explain(costs off, verbose)
select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having avg(c2) > 95;
QUERY PLAN
----------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Output: mc1, mc3, (avg(mc2))
-> HashAggregate
Output: mc1, mc3, avg(mc2)
Group Key: aqumv_mvt4_0.mc1, aqumv_mvt4_0.mc3
Filter: (avg(aqumv_mvt4_0.mc2) > '95'::numeric)
-> Seq Scan on public.aqumv_mvt4_0
Output: mc1, mc2, mc3
Settings: enable_answer_query_using_materialized_views = 'on', optimizer = 'off'
Optimizer: Postgres query optimizer
(10 rows)

select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having avg(c2) > 95;
c1 | c3 | avg
-----+-----+----------------------
98 | 100 | 99.0000000000000000
95 | 97 | 96.0000000000000000
99 | 101 | 100.0000000000000000
97 | 99 | 98.0000000000000000
100 | 102 | 101.0000000000000000
96 | 98 | 97.0000000000000000
(6 rows)

-- duplicated having quals with where quals.
explain(costs off, verbose)
select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having c1 > 90;
QUERY PLAN
----------------------------------------------------------------------------------
Gather Motion 3:1 (slice1; segments: 3)
Output: mc1, mc3, (avg(mc2))
-> HashAggregate
Output: mc1, mc3, avg(mc2)
Group Key: aqumv_mvt4_0.mc1, aqumv_mvt4_0.mc3
-> Seq Scan on public.aqumv_mvt4_0
Output: mc1, mc2, mc3
Settings: enable_answer_query_using_materialized_views = 'on', optimizer = 'off'
Optimizer: Postgres query optimizer
(9 rows)

abort;
reset optimizer;
reset enable_answer_query_using_materialized_views;
Expand Down
40 changes: 40 additions & 0 deletions src/test/regress/sql/aqumv.sql
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,46 @@ select c1, c3, count(c2) from aqumv_t3 where c1 > 90 group by cube(c1, c3);
select c1, c3, count(c2) from aqumv_t3 where c1 > 90 group by cube(c1, c3);
abort;

--
-- Test HAVING clause
--
begin;
create table aqumv_t4(c1 int, c2 int, c3 int) distributed by (c1);
insert into aqumv_t4 select i, i+1, i+2 from generate_series(1, 100) i;
insert into aqumv_t4 values (91, NULL, 95);
analyze aqumv_t4;

create incremental materialized view aqumv_mvt4_0 as
select c1 as mc1, c2 as mc2, c3 as mc3
from aqumv_t4 where c1 > 90;
analyze aqumv_mvt4_0;

-- HAVING clause pushed down to where quals.
set local enable_answer_query_using_materialized_views = off;
explain(costs off, verbose)
select c1, c3 from aqumv_t4 where c1 > 90 group by (c1, c3) having c3 > 97 ;
select c1, c3 from aqumv_t4 where c1 > 90 group by (c1, c3) having c3 > 97 ;
set local enable_answer_query_using_materialized_views = on;
explain(costs off, verbose)
select c1, c3 from aqumv_t4 where c1 > 90 group by (c1, c3) having c3 > 97 ;
select c1, c3 from aqumv_t4 where c1 > 90 group by (c1, c3) having c3 > 97 ;

-- quals kept in HAVING clause.
set local enable_answer_query_using_materialized_views = off;
explain(costs off, verbose)
select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having avg(c2) > 95;
select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having avg(c2) > 95;
set local enable_answer_query_using_materialized_views = on;
explain(costs off, verbose)
select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having avg(c2) > 95;
select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having avg(c2) > 95;

-- duplicated having quals with where quals.
explain(costs off, verbose)
select c1, c3, avg(c2) from aqumv_t4 where c1 > 90 group by (c1, c3) having c1 > 90;

abort;

reset optimizer;
reset enable_answer_query_using_materialized_views;
drop table aqumv_t1 cascade;