diff --git a/src/backend/parser/parse_agg.c b/src/backend/parser/parse_agg.c index 21709b72ba3..58a4bd68a91 100644 --- a/src/backend/parser/parse_agg.c +++ b/src/backend/parser/parse_agg.c @@ -115,18 +115,6 @@ transformAggregateCall(ParseState *pstate, Aggref *agg, int save_next_resno; ListCell *lc; - /* - * Before separating the args into direct and aggregated args, make a list - * of their data type OIDs for use later. - */ - foreach(lc, args) - { - Expr *arg = (Expr *) lfirst(lc); - - argtypes = lappend_oid(argtypes, exprType((Node *) arg)); - } - agg->aggargtypes = argtypes; - if (AGGKIND_IS_ORDERED_SET(agg->aggkind)) { /* @@ -238,6 +226,29 @@ transformAggregateCall(ParseState *pstate, Aggref *agg, agg->aggorder = torder; agg->aggdistinct = tdistinct; + /* + * Now build the aggargtypes list with the type OIDs of the direct and + * aggregated args, ignoring any resjunk entries that might have been + * added by ORDER BY/DISTINCT processing. We can't do this earlier + * because said processing can modify some args' data types, in particular + * by resolving previously-unresolved "unknown" literals. + */ + foreach(lc, agg->aggdirectargs) + { + Expr *arg = (Expr *) lfirst(lc); + + argtypes = lappend_oid(argtypes, exprType((Node *) arg)); + } + foreach(lc, tlist) + { + TargetEntry *tle = (TargetEntry *) lfirst(lc); + + if (tle->resjunk) + continue; /* ignore junk */ + argtypes = lappend_oid(argtypes, exprType((Node *) tle->expr)); + } + agg->aggargtypes = argtypes; + check_agglevels_and_constraints(pstate, (Node *) agg); } diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index ebb973cb151..635016d4aad 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -1558,6 +1558,13 @@ SELECT jsonb_object_agg(name, type) FROM foo; INSERT INTO foo VALUES (999999, NULL, 'bar'); SELECT jsonb_object_agg(name, type) FROM foo; ERROR: field name must not be null +-- edge case for parser +SELECT jsonb_object_agg(DISTINCT 'a', 'abc'); + jsonb_object_agg +------------------ + {"a": "abc"} +(1 row) + -- jsonb_object -- empty object, one dimension SELECT jsonb_object('{}'); diff --git a/src/test/regress/expected/jsonb_optimizer.out b/src/test/regress/expected/jsonb_optimizer.out index 6250207107a..1f5510c9982 100644 --- a/src/test/regress/expected/jsonb_optimizer.out +++ b/src/test/regress/expected/jsonb_optimizer.out @@ -1560,6 +1560,13 @@ SELECT jsonb_object_agg(name, type) FROM foo; INSERT INTO foo VALUES (999999, NULL, 'bar'); SELECT jsonb_object_agg(name, type) FROM foo; ERROR: field name must not be null +-- edge case for parser +SELECT jsonb_object_agg(DISTINCT 'a', 'abc'); + jsonb_object_agg +------------------ + {"a": "abc"} +(1 row) + -- jsonb_object -- empty object, one dimension SELECT jsonb_object('{}'); diff --git a/src/test/regress/sql/jsonb.sql b/src/test/regress/sql/jsonb.sql index 40cb055c11e..b1ce452a822 100644 --- a/src/test/regress/sql/jsonb.sql +++ b/src/test/regress/sql/jsonb.sql @@ -397,6 +397,9 @@ SELECT jsonb_object_agg(name, type) FROM foo; INSERT INTO foo VALUES (999999, NULL, 'bar'); SELECT jsonb_object_agg(name, type) FROM foo; +-- edge case for parser +SELECT jsonb_object_agg(DISTINCT 'a', 'abc'); + -- jsonb_object -- empty object, one dimension