diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index b207b8d913b..96ee312ebdf 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -810,6 +810,17 @@ create_agg_clause_infos(PlannerInfo *root) Assert(aggref->aggorder == NIL); Assert(aggref->aggdistinct == NIL); + /* + * We cannot push down aggregates that contain volatile functions. + * Doing so would change the number of times the function is + * evaluated. + */ + if (contain_volatile_functions((Node *) aggref)) + { + eager_agg_applicable = false; + break; + } + /* * If there are any securityQuals, do not try to apply eager * aggregation if any non-leakproof aggregate functions are present. diff --git a/src/test/regress/expected/eager_aggregate.out b/src/test/regress/expected/eager_aggregate.out index 5ac966186f7..456d32eb13d 100644 --- a/src/test/regress/expected/eager_aggregate.out +++ b/src/test/regress/expected/eager_aggregate.out @@ -428,6 +428,44 @@ GROUP BY t1.a ORDER BY t1.a; RESET geqo; RESET geqo_threshold; +-- Ensure eager aggregation is not applied because random() is a volatile +-- function +EXPLAIN (COSTS OFF) +SELECT t1.a, avg(t2.c + random()) + FROM eager_agg_t1 t1 + JOIN eager_agg_t2 t2 ON t1.b = t2.b +GROUP BY t1.a ORDER BY t1.a; + QUERY PLAN +----------------------------------------------------- + GroupAggregate + Group Key: t1.a + -> Sort + Sort Key: t1.a + -> Hash Join + Hash Cond: (t2.b = t1.b) + -> Seq Scan on eager_agg_t2 t2 + -> Hash + -> Seq Scan on eager_agg_t1 t1 +(9 rows) + +EXPLAIN (COSTS OFF) +SELECT t1.a, avg(t2.c) FILTER (WHERE random() > 0.5) + FROM eager_agg_t1 t1 + JOIN eager_agg_t2 t2 ON t1.b = t2.b +GROUP BY t1.a ORDER BY t1.a; + QUERY PLAN +----------------------------------------------------- + GroupAggregate + Group Key: t1.a + -> Sort + Sort Key: t1.a + -> Hash Join + Hash Cond: (t2.b = t1.b) + -> Seq Scan on eager_agg_t2 t2 + -> Hash + -> Seq Scan on eager_agg_t1 t1 +(9 rows) + DROP TABLE eager_agg_t1; DROP TABLE eager_agg_t2; DROP TABLE eager_agg_t3; diff --git a/src/test/regress/sql/eager_aggregate.sql b/src/test/regress/sql/eager_aggregate.sql index abe6d6ae09f..53d9b377a64 100644 --- a/src/test/regress/sql/eager_aggregate.sql +++ b/src/test/regress/sql/eager_aggregate.sql @@ -163,6 +163,20 @@ GROUP BY t1.a ORDER BY t1.a; RESET geqo; RESET geqo_threshold; +-- Ensure eager aggregation is not applied because random() is a volatile +-- function +EXPLAIN (COSTS OFF) +SELECT t1.a, avg(t2.c + random()) + FROM eager_agg_t1 t1 + JOIN eager_agg_t2 t2 ON t1.b = t2.b +GROUP BY t1.a ORDER BY t1.a; + +EXPLAIN (COSTS OFF) +SELECT t1.a, avg(t2.c) FILTER (WHERE random() > 0.5) + FROM eager_agg_t1 t1 + JOIN eager_agg_t2 t2 ON t1.b = t2.b +GROUP BY t1.a ORDER BY t1.a; + DROP TABLE eager_agg_t1; DROP TABLE eager_agg_t2; DROP TABLE eager_agg_t3;