Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)