]> granicus.if.org Git - postgresql/commitdiff
Re-allow SRFs and window functions within sub-selects within aggregates.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 27 Jun 2017 21:51:11 +0000 (17:51 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 27 Jun 2017 21:51:11 +0000 (17:51 -0400)
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.

src/backend/parser/parse_agg.c
src/test/regress/expected/tsrf.out
src/test/regress/sql/tsrf.sql

index 613bdabd52071d66b87ec46be5bd4479946556de..64111f315e33a56bac17eb66549c7e3ef2076548 100644 (file)
@@ -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 */
index b691abe714666471435c03770c17229c7741e9bb..6d33fbd3c8ba1179767acab3498778305b347c6c 100644 (file)
@@ -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
index 0be7530beb4de7564b5fc07d86669ba2c4afb294..ae1900bce12ece7871b4f68c248959138c242f58 100644 (file)
@@ -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;