Skip to content

Commit 397c243

Browse files
author
Nikita Glukhov
committed
Add separate unique and strict variants of json[b] aggregate functions
1 parent fbf76e7 commit 397c243

File tree

6 files changed

+247
-37
lines changed

6 files changed

+247
-37
lines changed

doc/src/sgml/func.sgml

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18562,6 +18562,29 @@ SELECT NULLIF(value, '(none)') ...
1856218562
</para></entry>
1856318563
<entry>No</entry>
1856418564
</row>
18565+
18566+
<row>
18567+
<entry role="func_table_entry"><para role="func_signature">
18568+
<indexterm>
18569+
<primary>json_agg_strict</primary>
18570+
</indexterm>
18571+
<function>json_agg_strict</function> ( <type>anyelement</type> )
18572+
<returnvalue>json</returnvalue>
18573+
</para>
18574+
<para role="func_signature">
18575+
<indexterm>
18576+
<primary>jsonb_agg_strict</primary>
18577+
</indexterm>
18578+
<function>jsonb_agg_strict</function> ( <type>anyelement</type> )
18579+
<returnvalue>jsonb</returnvalue>
18580+
</para>
18581+
<para>
18582+
Collects all the input values, skipping nulls, into a JSON array.
18583+
Values are converted to JSON as per <function>to_json</function>
18584+
or <function>to_jsonb</function>.
18585+
</para></entry>
18586+
<entry>No</entry>
18587+
</row>
1856518588

1856618589
<row>
1856718590
<entry role="func_table_entry"><para role="func_signature">
@@ -18591,6 +18614,92 @@ SELECT NULLIF(value, '(none)') ...
1859118614
<entry>No</entry>
1859218615
</row>
1859318616

18617+
<row>
18618+
<entry role="func_table_entry"><para role="func_signature">
18619+
<indexterm>
18620+
<primary>json_object_agg_strict</primary>
18621+
</indexterm>
18622+
<function>json_object_agg_strict</function> (
18623+
<parameter>key</parameter> <type>"any"</type>,
18624+
<parameter>value</parameter> <type>"any"</type> )
18625+
<returnvalue>json</returnvalue>
18626+
</para>
18627+
<para role="func_signature">
18628+
<indexterm>
18629+
<primary>jsonb_object_agg_strict</primary>
18630+
</indexterm>
18631+
<function>jsonb_object_agg_strict</function> (
18632+
<parameter>key</parameter> <type>"any"</type>,
18633+
<parameter>value</parameter> <type>"any"</type> )
18634+
<returnvalue>jsonb</returnvalue>
18635+
</para>
18636+
<para>
18637+
Collects all the key/value pairs into a JSON object. Key arguments
18638+
are coerced to text; value arguments are converted as
18639+
per <function>to_json</function> or <function>to_jsonb</function>.
18640+
Null values are skipped, keys can not be null.
18641+
</para></entry>
18642+
<entry>No</entry>
18643+
</row>
18644+
18645+
<row>
18646+
<entry role="func_table_entry"><para role="func_signature">
18647+
<indexterm>
18648+
<primary>json_object_agg_unique</primary>
18649+
</indexterm>
18650+
<function>json_object_agg_unique</function> (
18651+
<parameter>key</parameter> <type>"any"</type>,
18652+
<parameter>value</parameter> <type>"any"</type> )
18653+
<returnvalue>json</returnvalue>
18654+
</para>
18655+
<para role="func_signature">
18656+
<indexterm>
18657+
<primary>jsonb_object_agg_unique</primary>
18658+
</indexterm>
18659+
<function>jsonb_object_agg_unique</function> (
18660+
<parameter>key</parameter> <type>"any"</type>,
18661+
<parameter>value</parameter> <type>"any"</type> )
18662+
<returnvalue>jsonb</returnvalue>
18663+
</para>
18664+
<para>
18665+
Collects all the key/value pairs into a JSON object. Key arguments
18666+
are coerced to text; value arguments are converted as
18667+
per <function>to_json</function> or <function>to_jsonb</function>.
18668+
Values can be null, but not keys.
18669+
In case of duplicate keys error is thrown.
18670+
</para></entry>
18671+
<entry>No</entry>
18672+
</row>
18673+
18674+
<row>
18675+
<entry role="func_table_entry"><para role="func_signature">
18676+
<indexterm>
18677+
<primary>json_object_agg_unique_strict</primary>
18678+
</indexterm>
18679+
<function>json_object_agg_unique_strict</function> (
18680+
<parameter>key</parameter> <type>"any"</type>,
18681+
<parameter>value</parameter> <type>"any"</type> )
18682+
<returnvalue>json</returnvalue>
18683+
</para>
18684+
<para role="func_signature">
18685+
<indexterm>
18686+
<primary>jsonb_object_agg_unique_strict</primary>
18687+
</indexterm>
18688+
<function>jsonb_object_agg_unique_strict</function> (
18689+
<parameter>key</parameter> <type>"any"</type>,
18690+
<parameter>value</parameter> <type>"any"</type> )
18691+
<returnvalue>jsonb</returnvalue>
18692+
</para>
18693+
<para>
18694+
Collects all the key/value pairs into a JSON object. Key arguments
18695+
are coerced to text; value arguments are converted as
18696+
per <function>to_json</function> or <function>to_jsonb</function>.
18697+
Null values are skipped, keys can not be null.
18698+
In case of duplicate keys error is thrown.
18699+
</para></entry>
18700+
<entry>No</entry>
18701+
</row>
18702+
1859418703
<row>
1859518704
<entry role="func_table_entry"><para role="func_signature">
1859618705
<indexterm>

src/backend/parser/parse_expr.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4116,22 +4116,38 @@ transformJsonObjectAgg(ParseState *pstate, JsonObjectAgg *agg)
41164116

41174117
key = transformExprRecurse(pstate, (Node *) agg->arg->key);
41184118
val = transformJsonValueExpr(pstate, agg->arg->value, JS_FORMAT_DEFAULT);
4119-
4120-
args = list_make4(key,
4121-
val,
4122-
makeBoolConst(agg->absent_on_null, false),
4123-
makeBoolConst(agg->unique, false));
4119+
args = list_make2(key, val);
41244120

41254121
returning = transformJsonCtorOutput(pstate, agg->ctor.output, args);
41264122

41274123
if (returning->format->format == JS_FORMAT_JSONB)
41284124
{
4129-
aggfnname = "pg_catalog.jsonb_objectagg"; /* F_JSONB_OBJECTAGG */
4125+
if (agg->absent_on_null)
4126+
if (agg->unique)
4127+
aggfnname = "pg_catalog.jsonb_object_agg_unique_strict"; /* F_JSONB_OBJECT_AGG_UNIQUE_STRICT */
4128+
else
4129+
aggfnname = "pg_catalog.jsonb_object_agg_strict"; /* F_JSONB_OBJECT_AGG_STRICT */
4130+
else
4131+
if (agg->unique)
4132+
aggfnname = "pg_catalog.jsonb_object_agg_unique"; /* F_JSONB_OBJECT_AGG_UNIQUE */
4133+
else
4134+
aggfnname = "pg_catalog.jsonb_object_agg"; /* F_JSONB_OBJECT_AGG */
4135+
41304136
aggtype = JSONBOID;
41314137
}
41324138
else
41334139
{
4134-
aggfnname = "pg_catalog.json_objectagg"; /* F_JSON_OBJECTAGG; */
4140+
if (agg->absent_on_null)
4141+
if (agg->unique)
4142+
aggfnname = "pg_catalog.json_object_agg_unique_strict"; /* F_JSON_OBJECT_AGG_UNIQUE_STRICT */
4143+
else
4144+
aggfnname = "pg_catalog.json_object_agg_strict"; /* F_JSON_OBJECT_AGG_STRICT */
4145+
else
4146+
if (agg->unique)
4147+
aggfnname = "pg_catalog.json_object_agg_unique"; /* F_JSON_OBJECT_AGG_UNIQUE */
4148+
else
4149+
aggfnname = "pg_catalog.json_object_agg"; /* F_JSON_OBJECT_AGG */
4150+
41354151
aggtype = JSONOID;
41364152
}
41374153

src/backend/utils/adt/json.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,14 +1156,30 @@ json_object_agg_transfn(PG_FUNCTION_ARGS)
11561156
}
11571157

11581158
/*
1159-
* json_objectagg aggregate function
1159+
* json_object_agg_strict aggregate function
11601160
*/
11611161
Datum
1162-
json_objectagg_transfn(PG_FUNCTION_ARGS)
1162+
json_object_agg_strict_transfn(PG_FUNCTION_ARGS)
11631163
{
1164-
return json_object_agg_transfn_worker(fcinfo,
1165-
PG_GETARG_BOOL(3),
1166-
PG_GETARG_BOOL(4));
1164+
return json_object_agg_transfn_worker(fcinfo, true, false);
1165+
}
1166+
1167+
/*
1168+
* json_object_agg_unique aggregate function
1169+
*/
1170+
Datum
1171+
json_object_agg_unique_transfn(PG_FUNCTION_ARGS)
1172+
{
1173+
return json_object_agg_transfn_worker(fcinfo, false, true);
1174+
}
1175+
1176+
/*
1177+
* json_object_agg_unique_strict aggregate function
1178+
*/
1179+
Datum
1180+
json_object_agg_unique_strict_transfn(PG_FUNCTION_ARGS)
1181+
{
1182+
return json_object_agg_transfn_worker(fcinfo, true, true);
11671183
}
11681184

11691185
/*

src/backend/utils/adt/jsonb.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,15 +1934,32 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
19341934
return jsonb_object_agg_transfn_worker(fcinfo, false, false);
19351935
}
19361936

1937+
1938+
/*
1939+
* jsonb_object_agg_strict aggregate function
1940+
*/
1941+
Datum
1942+
jsonb_object_agg_strict_transfn(PG_FUNCTION_ARGS)
1943+
{
1944+
return jsonb_object_agg_transfn_worker(fcinfo, true, false);
1945+
}
1946+
1947+
/*
1948+
* jsonb_object_agg_unique aggregate function
1949+
*/
1950+
Datum
1951+
jsonb_object_agg_unique_transfn(PG_FUNCTION_ARGS)
1952+
{
1953+
return jsonb_object_agg_transfn_worker(fcinfo, false, true);
1954+
}
1955+
19371956
/*
1938-
* jsonb_objectagg aggregate function
1957+
* jsonb_object_agg_unique_strict aggregate function
19391958
*/
19401959
Datum
1941-
jsonb_objectagg_transfn(PG_FUNCTION_ARGS)
1960+
jsonb_object_agg_unique_strict_transfn(PG_FUNCTION_ARGS)
19421961
{
1943-
return jsonb_object_agg_transfn_worker(fcinfo,
1944-
PG_GETARG_BOOL(3),
1945-
PG_GETARG_BOOL(4));
1962+
return jsonb_object_agg_transfn_worker(fcinfo, true, true);
19461963
}
19471964

19481965
Datum

src/include/catalog/pg_aggregate.dat

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,14 @@
545545
aggfinalfn => 'json_agg_finalfn', aggtranstype => 'internal' },
546546
{ aggfnoid => 'json_object_agg', aggtransfn => 'json_object_agg_transfn',
547547
aggfinalfn => 'json_object_agg_finalfn', aggtranstype => 'internal' },
548-
{ aggfnoid => 'json_objectagg', aggtransfn => 'json_objectagg_transfn',
548+
{ aggfnoid => 'json_object_agg_unique',
549+
aggtransfn => 'json_object_agg_unique_transfn',
550+
aggfinalfn => 'json_object_agg_finalfn', aggtranstype => 'internal' },
551+
{ aggfnoid => 'json_object_agg_strict',
552+
aggtransfn => 'json_object_agg_strict_transfn',
553+
aggfinalfn => 'json_object_agg_finalfn', aggtranstype => 'internal' },
554+
{ aggfnoid => 'json_object_agg_unique_strict',
555+
aggtransfn => 'json_object_agg_unique_strict_transfn',
549556
aggfinalfn => 'json_object_agg_finalfn', aggtranstype => 'internal' },
550557

551558
# jsonb
@@ -555,7 +562,14 @@
555562
aggfinalfn => 'jsonb_agg_finalfn', aggtranstype => 'internal' },
556563
{ aggfnoid => 'jsonb_object_agg', aggtransfn => 'jsonb_object_agg_transfn',
557564
aggfinalfn => 'jsonb_object_agg_finalfn', aggtranstype => 'internal' },
558-
{ aggfnoid => 'jsonb_objectagg', aggtransfn => 'jsonb_objectagg_transfn',
565+
{ aggfnoid => 'jsonb_object_agg_unique',
566+
aggtransfn => 'jsonb_object_agg_unique_transfn',
567+
aggfinalfn => 'jsonb_object_agg_finalfn', aggtranstype => 'internal' },
568+
{ aggfnoid => 'jsonb_object_agg_strict',
569+
aggtransfn => 'jsonb_object_agg_strict_transfn',
570+
aggfinalfn => 'jsonb_object_agg_finalfn', aggtranstype => 'internal' },
571+
{ aggfnoid => 'jsonb_object_agg_unique_strict',
572+
aggtransfn => 'jsonb_object_agg_unique_strict_transfn',
559573
aggfinalfn => 'jsonb_object_agg_finalfn', aggtranstype => 'internal' },
560574

561575
# ordered-set and hypothetical-set aggregates

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy