summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/parser/parse_agg.c28
-rw-r--r--src/test/regress/expected/with.out34
-rw-r--r--src/test/regress/sql/with.sql14
3 files changed, 75 insertions, 1 deletions
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 0ac8966e30f..3254c83cc6c 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -791,6 +791,32 @@ check_agg_arguments_walker(Node *node,
parser_errposition(context->pstate,
((WindowFunc *) node)->location)));
}
+
+ if (IsA(node, RangeTblEntry))
+ {
+ /*
+ * CTE references act similarly to Vars of the CTE's level. Without
+ * this we might conclude that the Agg can be evaluated above the CTE,
+ * leading to trouble.
+ */
+ RangeTblEntry *rte = (RangeTblEntry *) node;
+
+ if (rte->rtekind == RTE_CTE)
+ {
+ int ctelevelsup = rte->ctelevelsup;
+
+ /* convert levelsup to frame of reference of original query */
+ ctelevelsup -= context->sublevels_up;
+ /* ignore local CTEs of subqueries */
+ if (ctelevelsup >= 0)
+ {
+ if (context->min_varlevel < 0 ||
+ context->min_varlevel > ctelevelsup)
+ context->min_varlevel = ctelevelsup;
+ }
+ }
+ return false; /* allow range_table_walker to continue */
+ }
if (IsA(node, Query))
{
/* Recurse into subselects */
@@ -800,7 +826,7 @@ check_agg_arguments_walker(Node *node,
result = query_tree_walker((Query *) node,
check_agg_arguments_walker,
context,
- 0);
+ QTW_EXAMINE_RTES_BEFORE);
context->sublevels_up--;
return result;
}
diff --git a/src/test/regress/expected/with.out b/src/test/regress/expected/with.out
index f015e997276..c3932c7b94c 100644
--- a/src/test/regress/expected/with.out
+++ b/src/test/regress/expected/with.out
@@ -2298,6 +2298,40 @@ from int4_tbl;
(5 rows)
--
+-- test for bug #19055: interaction of WITH with aggregates
+--
+-- The reference to cte1 must determine the aggregate's level,
+-- even though it contains no Vars referencing cte1
+explain (verbose, costs off)
+select f1, (with cte1(x,y) as (select 1,2)
+ select count((select i4.f1 from cte1))) as ss
+from int4_tbl i4;
+ QUERY PLAN
+--------------------------------------------
+ Seq Scan on public.int4_tbl i4
+ Output: i4.f1, (SubPlan 2)
+ SubPlan 2
+ -> Aggregate
+ Output: count((InitPlan 1).col1)
+ InitPlan 1
+ -> Result
+ Output: i4.f1
+ -> Result
+(9 rows)
+
+select f1, (with cte1(x,y) as (select 1,2)
+ select count((select i4.f1 from cte1))) as ss
+from int4_tbl i4;
+ f1 | ss
+-------------+----
+ 0 | 1
+ 123456 | 1
+ -123456 | 1
+ 2147483647 | 1
+ -2147483647 | 1
+(5 rows)
+
+--
-- test for nested-recursive-WITH bug
--
WITH RECURSIVE t(j) AS (
diff --git a/src/test/regress/sql/with.sql b/src/test/regress/sql/with.sql
index b1cae161290..d88d5abb91a 100644
--- a/src/test/regress/sql/with.sql
+++ b/src/test/regress/sql/with.sql
@@ -1098,6 +1098,20 @@ select ( with cte(foo) as ( values(f1) )
from int4_tbl;
--
+-- test for bug #19055: interaction of WITH with aggregates
+--
+-- The reference to cte1 must determine the aggregate's level,
+-- even though it contains no Vars referencing cte1
+explain (verbose, costs off)
+select f1, (with cte1(x,y) as (select 1,2)
+ select count((select i4.f1 from cte1))) as ss
+from int4_tbl i4;
+
+select f1, (with cte1(x,y) as (select 1,2)
+ select count((select i4.f1 from cte1))) as ss
+from int4_tbl i4;
+
+--
-- test for nested-recursive-WITH bug
--
WITH RECURSIVE t(j) AS (