@@ -2598,6 +2598,9 @@ transformGroupingSet(List **flatresult,
25982598 * GROUP BY items will be added to the targetlist (as resjunk columns)
25992599 * if not already present, so the targetlist must be passed by reference.
26002600 *
2601+ * If GROUP BY ALL is specified, the groupClause will be inferred to be all
2602+ * non-aggregate, non-window expressions in the targetlist.
2603+ *
26012604 * This is also used for window PARTITION BY clauses (which act almost the
26022605 * same, but are always interpreted per SQL99 rules).
26032606 *
@@ -2622,14 +2625,16 @@ transformGroupingSet(List **flatresult,
26222625 *
26232626 * pstate ParseState
26242627 * grouplist clause to transform
2628+ * groupByAll is this a GROUP BY ALL statement?
26252629 * groupingSets reference to list to contain the grouping set tree
26262630 * targetlist reference to TargetEntry list
26272631 * sortClause ORDER BY clause (SortGroupClause nodes)
26282632 * exprKind expression kind
26292633 * useSQL99 SQL99 rather than SQL92 syntax
26302634 */
26312635List *
2632- transformGroupClause (ParseState * pstate , List * grouplist , List * * groupingSets ,
2636+ transformGroupClause (ParseState * pstate , List * grouplist , bool groupByAll ,
2637+ List * * groupingSets ,
26332638 List * * targetlist , List * sortClause ,
26342639 ParseExprKind exprKind , bool useSQL99 )
26352640{
@@ -2640,6 +2645,63 @@ transformGroupClause(ParseState *pstate, List *grouplist, List **groupingSets,
26402645 bool hasGroupingSets = false;
26412646 Bitmapset * seen_local = NULL ;
26422647
2648+ /* Handle GROUP BY ALL */
2649+ if (groupByAll )
2650+ {
2651+ /* There cannot have been any explicit grouplist items */
2652+ Assert (grouplist == NIL );
2653+
2654+ /* Iterate over targets, adding acceptable ones to the result list */
2655+ foreach_ptr (TargetEntry , tle , * targetlist )
2656+ {
2657+ /* Ignore junk TLEs */
2658+ if (tle -> resjunk )
2659+ continue ;
2660+
2661+ /*
2662+ * TLEs containing aggregates are not okay to add to GROUP BY
2663+ * (compare checkTargetlistEntrySQL92). But the SQL standard
2664+ * directs us to skip them, so it's fine.
2665+ */
2666+ if (pstate -> p_hasAggs &&
2667+ contain_aggs_of_level ((Node * ) tle -> expr , 0 ))
2668+ continue ;
2669+
2670+ /*
2671+ * Likewise, TLEs containing window functions are not okay to add
2672+ * to GROUP BY. At this writing, the SQL standard is silent on
2673+ * what to do with them, but by analogy to aggregates we'll just
2674+ * skip them.
2675+ */
2676+ if (pstate -> p_hasWindowFuncs &&
2677+ contain_windowfuncs ((Node * ) tle -> expr ))
2678+ continue ;
2679+
2680+ /*
2681+ * Otherwise, add the TLE to the result using default sort/group
2682+ * semantics. We specify the parse location as the TLE's
2683+ * location, despite the comment for addTargetToGroupList
2684+ * discouraging that. The only other thing we could point to is
2685+ * the ALL keyword, which seems unhelpful when there are multiple
2686+ * TLEs.
2687+ */
2688+ result = addTargetToGroupList (pstate , tle ,
2689+ result , * targetlist ,
2690+ exprLocation ((Node * ) tle -> expr ));
2691+ }
2692+
2693+ /* If we found any acceptable targets, we're done */
2694+ if (result != NIL )
2695+ return result ;
2696+
2697+ /*
2698+ * Otherwise, the SQL standard says to treat it like "GROUP BY ()".
2699+ * Build a representation of that, and let the rest of this function
2700+ * handle it.
2701+ */
2702+ grouplist = list_make1 (makeGroupingSet (GROUPING_SET_EMPTY , NIL , -1 ));
2703+ }
2704+
26432705 /*
26442706 * Recursively flatten implicit RowExprs. (Technically this is only needed
26452707 * for GROUP BY, per the syntax rules for grouping sets, but we do it
@@ -2818,6 +2880,7 @@ transformWindowDefinitions(ParseState *pstate,
28182880 true /* force SQL99 rules */ );
28192881 partitionClause = transformGroupClause (pstate ,
28202882 windef -> partitionClause ,
2883+ false /* not GROUP BY ALL */ ,
28212884 NULL ,
28222885 targetlist ,
28232886 orderClause ,
0 commit comments