summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2017-06-27 21:51:11 +0000
committerTom Lane2017-06-27 21:51:11 +0000
commit9c7dc89282b3dac5685c39d4d792b02ca573c2d3 (patch)
tree9bb7d8b895e2836134a4a39e6aa4193e02da14a7
parent2710ccd782d0308a3fa1ab193531183148e9b626 (diff)
Re-allow SRFs and window functions within sub-selects within aggregates.
check_agg_arguments_walker threw an error upon seeing a SRF or window function, but that is too aggressive: if the function is within a sub-select then it's perfectly fine. I broke the SRF case in commit 0436f6bde by copying the logic for window functions ... but that was broken too, and had been since commit eaccfded9. Repair both cases in HEAD, and the window function case back to 9.3. 9.2 gets this right.
-rw-r--r--src/backend/parser/parse_agg.c37
-rw-r--r--src/test/regress/expected/tsrf.out14
-rw-r--r--src/test/regress/sql/tsrf.sql6
3 files changed, 42 insertions, 15 deletions
diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c
index 613bdabd52..64111f315e 100644
--- a/src/backend/parser/parse_agg.c
+++ b/src/backend/parser/parse_agg.c
@@ -705,21 +705,28 @@ check_agg_arguments_walker(Node *node,
}
/* Continue and descend into subtree */
}
- /* We can throw error on sight for a set-returning function */
- if ((IsA(node, FuncExpr) &&((FuncExpr *) node)->funcretset) ||
- (IsA(node, OpExpr) &&((OpExpr *) node)->opretset))
- ereport(ERROR,
- (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("aggregate function calls cannot contain set-returning function calls"),
- errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
- parser_errposition(context->pstate, exprLocation(node))));
- /* We can throw error on sight for a window function */
- if (IsA(node, WindowFunc))
- ereport(ERROR,
- (errcode(ERRCODE_GROUPING_ERROR),
- errmsg("aggregate function calls cannot contain window function calls"),
- parser_errposition(context->pstate,
- ((WindowFunc *) node)->location)));
+
+ /*
+ * SRFs and window functions can be rejected immediately, unless we are
+ * within a sub-select within the aggregate's arguments; in that case
+ * they're OK.
+ */
+ if (context->sublevels_up == 0)
+ {
+ if ((IsA(node, FuncExpr) &&((FuncExpr *) node)->funcretset) ||
+ (IsA(node, OpExpr) &&((OpExpr *) node)->opretset))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("aggregate function calls cannot contain set-returning function calls"),
+ errhint("You might be able to move the set-returning function into a LATERAL FROM item."),
+ parser_errposition(context->pstate, exprLocation(node))));
+ if (IsA(node, WindowFunc))
+ ereport(ERROR,
+ (errcode(ERRCODE_GROUPING_ERROR),
+ errmsg("aggregate function calls cannot contain window function calls"),
+ parser_errposition(context->pstate,
+ ((WindowFunc *) node)->location)));
+ }
if (IsA(node, Query))
{
/* Recurse into subselects */
diff --git a/src/test/regress/expected/tsrf.out b/src/test/regress/expected/tsrf.out
index b691abe714..6d33fbd3c8 100644
--- a/src/test/regress/expected/tsrf.out
+++ b/src/test/regress/expected/tsrf.out
@@ -212,6 +212,20 @@ ERROR: aggregate function calls cannot contain set-returning function calls
LINE 1: SELECT min(generate_series(1, 3)) FROM few;
^
HINT: You might be able to move the set-returning function into a LATERAL FROM item.
+-- ... unless they're within a sub-select
+SELECT sum((3 = ANY(SELECT generate_series(1,4)))::int);
+ sum
+-----
+ 1
+(1 row)
+
+SELECT sum((3 = ANY(SELECT lag(x) over(order by x)
+ FROM generate_series(1,4) x))::int);
+ sum
+-----
+ 1
+(1 row)
+
-- SRFs are not allowed in window function arguments, either
SELECT min(generate_series(1, 3)) OVER() FROM few;
ERROR: window function calls cannot contain set-returning function calls
diff --git a/src/test/regress/sql/tsrf.sql b/src/test/regress/sql/tsrf.sql
index 0be7530beb..ae1900bce1 100644
--- a/src/test/regress/sql/tsrf.sql
+++ b/src/test/regress/sql/tsrf.sql
@@ -61,6 +61,12 @@ SELECT q1, coalesce(generate_series(1,3), 0) FROM int8_tbl;
-- SRFs are not allowed in aggregate arguments
SELECT min(generate_series(1, 3)) FROM few;
+-- ... unless they're within a sub-select
+SELECT sum((3 = ANY(SELECT generate_series(1,4)))::int);
+
+SELECT sum((3 = ANY(SELECT lag(x) over(order by x)
+ FROM generate_series(1,4) x))::int);
+
-- SRFs are not allowed in window function arguments, either
SELECT min(generate_series(1, 3)) OVER() FROM few;