typedefstruct
{
ParseState *pstate; int min_varlevel; int min_agglevel; int min_ctelevel;
RangeTblEntry *min_cte; int sublevels_up;
} check_agg_arguments_context;
typedefstruct
{
ParseState *pstate;
Query *qry; bool hasJoinRTEs;
List *groupClauses;
List *groupClauseCommonVars;
List *gset_common; bool have_non_var_grouping;
List **func_grouped_rels; int sublevels_up; bool in_agg_direct_args;
} substitute_grouped_columns_context;
staticint check_agg_arguments(ParseState *pstate,
List *directargs,
List *args,
Expr *filter, int agglocation); staticbool check_agg_arguments_walker(Node *node,
check_agg_arguments_context *context); static Node *substitute_grouped_columns(Node *node, ParseState *pstate, Query *qry,
List *groupClauses, List *groupClauseCommonVars,
List *gset_common, bool have_non_var_grouping,
List **func_grouped_rels); static Node *substitute_grouped_columns_mutator(Node *node,
substitute_grouped_columns_context *context); staticvoid finalize_grouping_exprs(Node *node, ParseState *pstate, Query *qry,
List *groupClauses, bool hasJoinRTEs, bool have_non_var_grouping); staticbool finalize_grouping_exprs_walker(Node *node,
substitute_grouped_columns_context *context); static Var *buildGroupedVar(int attnum, Index ressortgroupref,
substitute_grouped_columns_context *context); staticvoid check_agglevels_and_constraints(ParseState *pstate, Node *expr); static List *expand_groupingset_node(GroupingSet *gs); static Node *make_agg_arg(Oid argtype, Oid argcollation);
/* *transformAggregateCall- *Finishinitialtransformationofanaggregatecall * *parse_func.chasrecognizedthefunctionasanaggregate,andhassetup *allthefieldsoftheAggrefexceptaggargtypes,aggdirectargs,args, *aggorder,aggdistinctandagglevelsup.Thepassed-inargslisthasbeen *throughstandardexpressiontransformationandtypecoerciontomatchthe *agg'sdeclaredargtypes,whilethepassed-inaggorderlisthasn'tbeen *transformedatall. * *Hereweseparatetheargslistintodirectandaggregatedargs,storingthe *formerinagg->aggdirectargsandthelatterinagg->args.Theregular *args,butnotthedirectargs,areconvertedintoatargetlistbyinserting *TargetEntrynodes.Wethentransformtheaggorderandagg_distinct *specificationstoproducelistsofSortGroupClausenodesforagg->aggorder *andagg->aggdistinct.(Foraregularaggregate,thismightresultin *addingresjunkexpressionstothetargetlist;butforordered-set *aggregatestheaggorderlistwillalwaysbeone-to-onewiththeaggregated *args.) * *Wemustalsodeterminewhichqueryleveltheaggregateactuallybelongsto, *setagglevelsupaccordingly,andmarkp_hasAggstrueinthecorresponding *pstatelevel.
*/ void
transformAggregateCall(ParseState *pstate, Aggref *agg,
List *args, List *aggorder, bool agg_distinct)
{
List *argtypes = NIL;
List *tlist = NIL;
List *torder = NIL;
List *tdistinct = NIL;
AttrNumber attno = 1; int save_next_resno;
ListCell *lc;
if (AGGKIND_IS_ORDERED_SET(agg->aggkind))
{ /* *Foranordered-setagg,theargslistincludesdirectargsand *aggregatedargs;wemustsplitthemapart.
*/ int numDirectArgs = list_length(args) - list_length(aggorder);
List *aargs;
ListCell *lc2;
/* Never any DISTINCT in an ordered-set agg */
Assert(!agg_distinct);
} else
{ /* Regular aggregate, so it has no direct args */
agg->aggdirectargs = NIL;
if (!OidIsValid(sortcl->sortop))
{
Node *expr = get_sortgroupclause_expr(sortcl, tlist);
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FUNCTION),
errmsg("could not identify an ordering operator for type %s",
format_type_be(exprType(expr))),
errdetail("Aggregates with DISTINCT must be able to sort their inputs."),
parser_errposition(pstate, exprLocation(expr))));
}
}
}
pstate->p_next_resno = save_next_resno;
}
/* Update the Aggref with the transformation results */
agg->args = tlist;
agg->aggorder = torder;
agg->aggdistinct = tdistinct;
if (list_length(args) > 31)
ereport(ERROR,
(errcode(ERRCODE_TOO_MANY_ARGUMENTS),
errmsg("GROUPING must have fewer than 32 arguments"),
parser_errposition(pstate, p->location)));
/* *Acceptaggregate/groupinghere;callermustthrowerrorif *wanted
*/ break; case EXPR_KIND_JOIN_ON: case EXPR_KIND_JOIN_USING: if (isAgg)
err = _("aggregate functions are not allowed in JOIN conditions"); else
err = _("grouping operations are not allowed in JOIN conditions");
break; case EXPR_KIND_FROM_SUBSELECT:
/* *Aggregate/groupingscoperulesmakeitworthbeingexplicit *here
*/ if (isAgg)
err = _("aggregate functions are not allowed in FROM clause of their own query level"); else
err = _("grouping operations are not allowed in FROM clause of their own query level");
break; case EXPR_KIND_FROM_FUNCTION: if (isAgg)
err = _("aggregate functions are not allowed in functions in FROM"); else
err = _("grouping operations are not allowed in functions in FROM");
break; case EXPR_KIND_WHERE:
errkind = true; break; case EXPR_KIND_POLICY: if (isAgg)
err = _("aggregate functions are not allowed in policy expressions"); else
err = _("grouping operations are not allowed in policy expressions");
break; case EXPR_KIND_HAVING: /* okay */ break; case EXPR_KIND_FILTER:
errkind = true; break; case EXPR_KIND_WINDOW_PARTITION: /* okay */ break; case EXPR_KIND_WINDOW_ORDER: /* okay */ break; case EXPR_KIND_WINDOW_FRAME_RANGE: if (isAgg)
err = _("aggregate functions are not allowed in window RANGE"); else
err = _("grouping operations are not allowed in window RANGE");
break; case EXPR_KIND_WINDOW_FRAME_ROWS: if (isAgg)
err = _("aggregate functions are not allowed in window ROWS"); else
err = _("grouping operations are not allowed in window ROWS");
break; case EXPR_KIND_WINDOW_FRAME_GROUPS: if (isAgg)
err = _("aggregate functions are not allowed in window GROUPS"); else
err = _("grouping operations are not allowed in window GROUPS");
break; case EXPR_KIND_SELECT_TARGET: /* okay */ break; case EXPR_KIND_INSERT_TARGET: case EXPR_KIND_UPDATE_SOURCE: case EXPR_KIND_UPDATE_TARGET:
errkind = true; break; case EXPR_KIND_MERGE_WHEN: if (isAgg)
err = _("aggregate functions are not allowed in MERGE WHEN conditions"); else
err = _("grouping operations are not allowed in MERGE WHEN conditions");
break; case EXPR_KIND_GROUP_BY:
errkind = true; break; case EXPR_KIND_ORDER_BY: /* okay */ break; case EXPR_KIND_DISTINCT_ON: /* okay */ break; case EXPR_KIND_LIMIT: case EXPR_KIND_OFFSET:
errkind = true; break; case EXPR_KIND_RETURNING: case EXPR_KIND_MERGE_RETURNING:
errkind = true; break; case EXPR_KIND_VALUES: case EXPR_KIND_VALUES_SINGLE:
errkind = true; break; case EXPR_KIND_CHECK_CONSTRAINT: case EXPR_KIND_DOMAIN_CHECK: if (isAgg)
err = _("aggregate functions are not allowed in check constraints"); else
err = _("grouping operations are not allowed in check constraints");
break; case EXPR_KIND_COLUMN_DEFAULT: case EXPR_KIND_FUNCTION_DEFAULT:
if (isAgg)
err = _("aggregate functions are not allowed in DEFAULT expressions"); else
err = _("grouping operations are not allowed in DEFAULT expressions");
break; case EXPR_KIND_INDEX_EXPRESSION: if (isAgg)
err = _("aggregate functions are not allowed in index expressions"); else
err = _("grouping operations are not allowed in index expressions");
break; case EXPR_KIND_INDEX_PREDICATE: if (isAgg)
err = _("aggregate functions are not allowed in index predicates"); else
err = _("grouping operations are not allowed in index predicates");
break; case EXPR_KIND_STATS_EXPRESSION: if (isAgg)
err = _("aggregate functions are not allowed in statistics expressions"); else
err = _("grouping operations are not allowed in statistics expressions");
break; case EXPR_KIND_ALTER_COL_TRANSFORM: if (isAgg)
err = _("aggregate functions are not allowed in transform expressions"); else
err = _("grouping operations are not allowed in transform expressions");
break; case EXPR_KIND_EXECUTE_PARAMETER: if (isAgg)
err = _("aggregate functions are not allowed in EXECUTE parameters"); else
err = _("grouping operations are not allowed in EXECUTE parameters");
break; case EXPR_KIND_TRIGGER_WHEN: if (isAgg)
err = _("aggregate functions are not allowed in trigger WHEN conditions"); else
err = _("grouping operations are not allowed in trigger WHEN conditions");
break; case EXPR_KIND_PARTITION_BOUND: if (isAgg)
err = _("aggregate functions are not allowed in partition bound"); else
err = _("grouping operations are not allowed in partition bound");
break; case EXPR_KIND_PARTITION_EXPRESSION: if (isAgg)
err = _("aggregate functions are not allowed in partition key expressions"); else
err = _("grouping operations are not allowed in partition key expressions");
break; case EXPR_KIND_GENERATED_COLUMN:
if (isAgg)
err = _("aggregate functions are not allowed in column generation expressions"); else
err = _("grouping operations are not allowed in column generation expressions");
break;
case EXPR_KIND_CALL_ARGUMENT: if (isAgg)
err = _("aggregate functions are not allowed in CALL arguments"); else
err = _("grouping operations are not allowed in CALL arguments");
break;
case EXPR_KIND_COPY_WHERE: if (isAgg)
err = _("aggregate functions are not allowed in COPY FROM WHERE conditions"); else
err = _("grouping operations are not allowed in COPY FROM WHERE conditions");
if (err)
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg_internal("%s", err),
parser_errposition(pstate, location)));
if (errkind)
{ if (isAgg) /* translator: %s is name of a SQL construct, eg GROUP BY */
err = _("aggregate functions are not allowed in %s"); else /* translator: %s is name of a SQL construct, eg GROUP BY */
err = _("grouping operations are not allowed in %s");
/* *Ifthere'sanestedaggregateofthesamesemanticlevel,complain.
*/ if (agglevel == context.min_agglevel)
{ int aggloc;
aggloc = locate_agg_of_level((Node *) args, agglevel); if (aggloc < 0)
aggloc = locate_agg_of_level((Node *) filter, agglevel);
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("aggregate function calls cannot be nested"),
parser_errposition(pstate, aggloc)));
}
/* *Ifthere'sanon-localCTEthat'sbelowtheaggregate'ssemanticlevel, *complain.It'snotquiteclearwhatweshoulddotofixupsuchacase *(treatingtheCTEreferencelikeaVarseemswrong),andit'salso *unclearwhetherthereisareal-worlduseforsuchcases.
*/ if (context.min_ctelevel >= 0 && context.min_ctelevel < agglevel)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("outer-level aggregate cannot use a nested CTE"),
errdetail("CTE \"%s\" is below the aggregate's semantic level.",
context.min_cte->eref->aliasname),
parser_errposition(pstate, agglocation)));
/* *Nowcheckforvars/aggsinthedirectarguments,andthrowerrorif *needed.NotethatweallowaVaroftheagg'ssemanticlevel,butnot *anAggofthatlevel.InprinciplesuchAggscouldprobablybe *supported,butitwouldcreateanorderingdependencyamongthe *aggregatesatexecutiontime.Sincethecaseappearsneithertobe *requiredbyspecnorparticularlyuseful,wejusttreatitasa *nested-aggregatesituation.
*/ if (directargs)
{
context.min_varlevel = -1;
context.min_agglevel = -1;
context.min_ctelevel = -1;
(void) check_agg_arguments_walker((Node *) directargs, &context); if (context.min_varlevel >= 0 && context.min_varlevel < agglevel)
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("outer-level aggregate cannot contain a lower-level variable in its direct arguments"),
parser_errposition(pstate,
locate_var_of_level((Node *) directargs,
context.min_varlevel)))); if (context.min_agglevel >= 0 && context.min_agglevel <= agglevel)
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("aggregate function calls cannot be nested"),
parser_errposition(pstate,
locate_agg_of_level((Node *) directargs,
context.min_agglevel)))); if (context.min_ctelevel >= 0 && context.min_ctelevel < agglevel)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("outer-level aggregate cannot use a nested CTE"),
errdetail("CTE \"%s\" is below the aggregate's semantic level.",
context.min_cte->eref->aliasname),
parser_errposition(pstate, agglocation)));
} return agglevel;
}
staticbool
check_agg_arguments_walker(Node *node,
check_agg_arguments_context *context)
{ if (node == NULL) returnfalse; if (IsA(node, Var))
{ int varlevelsup = ((Var *) node)->varlevelsup;
/* convert levelsup to frame of reference of original query */
varlevelsup -= context->sublevels_up; /* ignore local vars of subqueries */ if (varlevelsup >= 0)
{ if (context->min_varlevel < 0 ||
context->min_varlevel > varlevelsup)
context->min_varlevel = varlevelsup;
} returnfalse;
} if (IsA(node, Aggref))
{ int agglevelsup = ((Aggref *) node)->agglevelsup;
/* convert levelsup to frame of reference of original query */
agglevelsup -= context->sublevels_up; /* ignore local aggs of subqueries */ if (agglevelsup >= 0)
{ if (context->min_agglevel < 0 ||
context->min_agglevel > agglevelsup)
context->min_agglevel = agglevelsup;
} /* Continue and descend into subtree */
} if (IsA(node, GroupingFunc))
{ int agglevelsup = ((GroupingFunc *) node)->agglevelsup;
/* convert levelsup to frame of reference of original query */
agglevelsup -= context->sublevels_up; /* ignore local aggs of subqueries */ if (agglevelsup >= 0)
{ if (context->min_agglevel < 0 ||
context->min_agglevel > agglevelsup)
context->min_agglevel = agglevelsup;
} /* Continue and descend into subtree */
}
/* *SRFsandwindowfunctionscanberejectedimmediately,unlessweare *withinasub-selectwithintheaggregate'sarguments;inthatcase *they'reOK.
*/ 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, RangeTblEntry))
{
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_ctelevel < 0 ||
context->min_ctelevel > ctelevelsup)
{
context->min_ctelevel = ctelevelsup;
context->min_cte = rte;
}
}
} returnfalse; /* allow range_table_walker to continue */
} if (IsA(node, Query))
{ /* Recurse into subselects */ bool result;
/* *Awindowfunctioncallcan'tcontainanotherone(butaggsareOK).XXX *isthisrequiredbyspec,orjustanunimplementedfeature? * *Note:wedon'tneedtocheckthefilterexpressionhere,becausethe *contextchecksdonebelowandintransformAggregateCallwouldhave *alreadyrejectedanywindowfuncsoraggswithinthefilter.
*/ if (pstate->p_hasWindowFuncs &&
contain_windowfuncs((Node *) wfunc->args))
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg("window function calls cannot be nested"),
parser_errposition(pstate,
locate_windowfunc((Node *) wfunc->args))));
/* *Checktoseeifthewindowfunctionisinaninvalidplacewithinthe *query. * *Forbrevitywesupporttwoschemesforreportinganerrorhere:set *"err"toacustommessage,orset"errkind"trueiftheerrorcontext *issufficientlyidentifiedbywhatParseExprKindNamewillreturn,*and* *whatitwillreturnisjustaSQLkeyword.(Otherwise,useacustom *messagetoavoidcreatingtranslationproblems.)
*/
err = NULL;
errkind = false; switch (pstate->p_expr_kind)
{ case EXPR_KIND_NONE:
Assert(false); /* can't happen */ break; case EXPR_KIND_OTHER: /* Accept window func here; caller must throw error if wanted */ break; case EXPR_KIND_JOIN_ON: case EXPR_KIND_JOIN_USING:
err = _("window functions are not allowed in JOIN conditions"); break; case EXPR_KIND_FROM_SUBSELECT: /* can't get here, but just in case, throw an error */
errkind = true; break; case EXPR_KIND_FROM_FUNCTION:
err = _("window functions are not allowed in functions in FROM"); break; case EXPR_KIND_WHERE:
errkind = true; break; case EXPR_KIND_POLICY:
err = _("window functions are not allowed in policy expressions"); break; case EXPR_KIND_HAVING:
errkind = true; break; case EXPR_KIND_FILTER:
errkind = true; break; case EXPR_KIND_WINDOW_PARTITION: case EXPR_KIND_WINDOW_ORDER: case EXPR_KIND_WINDOW_FRAME_RANGE: case EXPR_KIND_WINDOW_FRAME_ROWS: case EXPR_KIND_WINDOW_FRAME_GROUPS:
err = _("window functions are not allowed in window definitions"); break; case EXPR_KIND_SELECT_TARGET: /* okay */ break; case EXPR_KIND_INSERT_TARGET: case EXPR_KIND_UPDATE_SOURCE: case EXPR_KIND_UPDATE_TARGET:
errkind = true; break; case EXPR_KIND_MERGE_WHEN:
err = _("window functions are not allowed in MERGE WHEN conditions"); break; case EXPR_KIND_GROUP_BY:
errkind = true; break; case EXPR_KIND_ORDER_BY: /* okay */ break; case EXPR_KIND_DISTINCT_ON: /* okay */ break; case EXPR_KIND_LIMIT: case EXPR_KIND_OFFSET:
errkind = true; break; case EXPR_KIND_RETURNING: case EXPR_KIND_MERGE_RETURNING:
errkind = true; break; case EXPR_KIND_VALUES: case EXPR_KIND_VALUES_SINGLE:
errkind = true; break; case EXPR_KIND_CHECK_CONSTRAINT: case EXPR_KIND_DOMAIN_CHECK:
err = _("window functions are not allowed in check constraints"); break; case EXPR_KIND_COLUMN_DEFAULT: case EXPR_KIND_FUNCTION_DEFAULT:
err = _("window functions are not allowed in DEFAULT expressions"); break; case EXPR_KIND_INDEX_EXPRESSION:
err = _("window functions are not allowed in index expressions"); break; case EXPR_KIND_STATS_EXPRESSION:
err = _("window functions are not allowed in statistics expressions"); break; case EXPR_KIND_INDEX_PREDICATE:
err = _("window functions are not allowed in index predicates"); break; case EXPR_KIND_ALTER_COL_TRANSFORM:
err = _("window functions are not allowed in transform expressions"); break; case EXPR_KIND_EXECUTE_PARAMETER:
err = _("window functions are not allowed in EXECUTE parameters"); break; case EXPR_KIND_TRIGGER_WHEN:
err = _("window functions are not allowed in trigger WHEN conditions"); break; case EXPR_KIND_PARTITION_BOUND:
err = _("window functions are not allowed in partition bound"); break; case EXPR_KIND_PARTITION_EXPRESSION:
err = _("window functions are not allowed in partition key expressions"); break; case EXPR_KIND_CALL_ARGUMENT:
err = _("window functions are not allowed in CALL arguments"); break; case EXPR_KIND_COPY_WHERE:
err = _("window functions are not allowed in COPY FROM WHERE conditions"); break; case EXPR_KIND_GENERATED_COLUMN:
err = _("window functions are not allowed in column generation expressions"); break; case EXPR_KIND_CYCLE_MARK:
errkind = true; break;
/* *Thereisintentionallynodefault:casehere,sothatthe *compilerwillwarnifweaddanewParseExprKindwithout *extendingthisswitch.Ifwedoseeanunrecognizedvalueat *runtime,thebehaviorwillbethesameasforEXPR_KIND_OTHER, *whichissaneanyway.
*/
} if (err)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR),
errmsg_internal("%s", err),
parser_errposition(pstate, wfunc->location))); if (errkind)
ereport(ERROR,
(errcode(ERRCODE_WINDOWING_ERROR), /* translator: %s is name of a SQL construct, eg GROUP BY */
errmsg("window functions are not allowed in %s",
ParseExprKindName(pstate->p_expr_kind)),
parser_errposition(pstate, wfunc->location)));
/* *IftheOVERclausejustspecifiesawindowname,findthatWINDOW *clause(whichhadbetterbepresent).Otherwise,trytomatchallthe *propertiesoftheOVERclause,andmakeanewentryinthep_windowdefs *listifnoluck.
*/ if (windef->name)
{
Index winref = 0;
ListCell *lc;
/* This should only be called if we found aggregates or grouping */
Assert(pstate->p_hasAggs || qry->groupClause || qry->havingQual || qry->groupingSets);
/* *Ifwehavegroupingsets,expandthemandfindtheintersectionofall *sets.
*/ if (qry->groupingSets)
{ /* *Thelimitof4096isarbitraryandexistssimplytoavoidresource *issuesfrompathologicalconstructs.
*/
List *gsets = expand_grouping_sets(qry->groupingSets, qry->groupDistinct, 4096);
/* Set qry->rtable again in case it was previously NIL */
qry->rtable = pstate->p_rtable; /* Mark the Query as having RTE_GROUP RTE */
qry->hasGroupRTE = true;
}
attnum++; if (equal(node, tle->expr))
{ /* acceptable, replace it with a GROUP Var */ return (Node *) buildGroupedVar(attnum,
tle->ressortgroupref,
context);
}
}
}
/* Found an ungrouped local variable; generate error message */
attname = get_rte_attribute_name(rte, var->varattno); if (context->sublevels_up == 0)
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("column \"%s.%s\" must appear in the GROUP BY clause or be used in an aggregate function",
rte->eref->aliasname, attname),
context->in_agg_direct_args ?
errdetail("Direct arguments of an ordered-set aggregate must use only grouped columns.") : 0,
parser_errposition(context->pstate, var->location))); else
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("subquery uses ungrouped column \"%s.%s\" from outer query",
rte->eref->aliasname, attname),
parser_errposition(context->pstate, var->location)));
}
if (IsA(node, Query))
{ /* Recurse into subselects */
Query *newnode;
if (ref == 0)
ereport(ERROR,
(errcode(ERRCODE_GROUPING_ERROR),
errmsg("arguments to GROUPING must be grouping expressions of the associated query level"),
parser_errposition(context->pstate,
exprLocation(expr))));
ref_list = lappend_int(ref_list, ref);
}
grp->refs = ref_list;
}
if ((int) grp->agglevelsup > context->sublevels_up) returnfalse;
}
if (IsA(node, Query))
{ /* Recurse into subselects */ bool result;
if (mask & i)
current_result = list_concat(current_result,
gs_current->content);
mask <<= 1;
}
result = lappend(result, current_result);
}
} break;
case GROUPING_SET_SETS:
{
ListCell *lc;
foreach(lc, gs->content)
{
List *current_result = expand_groupingset_node(lfirst(lc));
result = list_concat(result, current_result);
}
} break;
}
return result;
}
/* list_sort comparator to sort sub-lists by length */ staticint
cmp_list_len_asc(const ListCell *a, const ListCell *b)
{ int la = list_length((const List *) lfirst(a)); int lb = list_length((const List *) lfirst(b));
return pg_cmp_s32(la, lb);
}
/* list_sort comparator to sort sub-lists by length and contents */ staticint
cmp_list_len_contents_asc(const ListCell *a, const ListCell *b)
{ int res = cmp_list_len_asc(a, b);
if (res == 0)
{
List *la = (List *) lfirst(a);
List *lb = (List *) lfirst(b);
ListCell *lca;
ListCell *lcb;
forboth(lca, la, lcb, lb)
{ int va = lfirst_int(lca); int vb = lfirst_int(lcb);
if (va > vb) return1; if (va < vb) return -1;
}
}
return res;
}
/* *ExpandagroupingSetsclausetoaflatlistofgroupingsets. *Thereturnedlistissortedbylength,shortestsetsfirst. * *Thisismainlyfortheplanner,butweuseitheretootodo *someconsistencychecks.
*/
List *
expand_grouping_sets(List *groupingSets, bool groupDistinct, int limit)
{
List *expanded_groups = NIL;
List *result = NIL; double numsets = 1;
ListCell *lc;
/* Now sort the lists by length and deduplicate if necessary */ if (!groupDistinct || list_length(result) < 2)
list_sort(result, cmp_list_len_asc); else
{
ListCell *cell;
List *prev;
/* Sort each groupset individually */
foreach(cell, result)
list_sort(lfirst(cell), list_int_cmp);
/* Now sort the list of groupsets by length and contents */
list_sort(result, cmp_list_len_contents_asc);
/* *resolve_aggregate_transtype *Identifythetransitionstatevalue'sdatatypeforanaggregatecall. * *Thisfunctionresolvesapolymorphicaggregate'sstatedatatype. *Itmustbepassedtheaggtranstypefromtheaggregate'scatalogentry, *aswellastheactualargumenttypesextractedbyget_aggregate_argtypes. *(Wecouldfetchpg_aggregate.aggtranstypeinternally,butallexisting *callersalreadyhavethevalueathand,sowemakethempassit.)
*/
Oid
resolve_aggregate_transtype(Oid aggfuncid,
Oid aggtranstype,
Oid *inputTypes, int numArguments)
{ /* resolve actual type of transition state, if polymorphic */ if (IsPolymorphicType(aggtranstype))
{ /* have to fetch the agg's declared input types... */
Oid *declaredArgTypes; int agg_nargs;
/* *Likebuild_aggregate_transfn_expr,butcreatesanexpressiontreeforthe *finalfunctionofanaggregate,ratherthanthetransitionfunction.
*/ void
build_aggregate_finalfn_expr(Oid *agg_input_types, int num_finalfn_inputs,
Oid agg_state_type,
Oid agg_result_type,
Oid agg_input_collation,
Oid finalfn_oid,
Expr **finalfnexpr)
{
List *args; int i;
/* finalfn may take additional args, which match agg's input types */ for (i = 0; i < num_finalfn_inputs - 1; i++)
{
args = lappend(args,
make_agg_arg(agg_input_types[i], agg_input_collation));
}
*finalfnexpr = (Expr *) makeFuncExpr(finalfn_oid,
agg_result_type,
args,
InvalidOid,
agg_input_collation,
COERCE_EXPLICIT_CALL); /* finalfn is currently never treated as variadic */
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.56Bemerkung:
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.