Skip to content

Commit 75f4598

Browse files
author
Nikita Glukhov
committed
Add json[b]_extract_keys()
1 parent dc06809 commit 75f4598

File tree

3 files changed

+39
-13
lines changed

3 files changed

+39
-13
lines changed

src/backend/utils/adt/json.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#define jsonb_object_field json_object_field
5858
#define jsonb_object_field_text json_object_field_text
5959
#define jsonb_object_keys json_object_keys
60+
#define jsonb_extract_keys json_extract_keys
6061
#define jsonb_populate_record json_populate_record
6162
#define jsonb_populate_recordset json_populate_recordset
6263
#define jsonb_pretty json_pretty

src/backend/utils/adt/jsonfuncs.c

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -572,8 +572,8 @@ makeJsonLexContext(text *json, bool need_escapes)
572572
* limited in size to NAMEDATALEN and the number of keys is unlikely to
573573
* be so huge that it has major memory implications.
574574
*/
575-
Datum
576-
jsonb_object_keys(PG_FUNCTION_ARGS)
575+
static Datum
576+
jsonb_extract_keys_internal(FunctionCallInfo fcinfo, bool outermost)
577577
{
578578
FuncCallContext *funcctx;
579579
OkeysState *state;
@@ -587,18 +587,25 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
587587
JsonbValue v;
588588
JsonbIteratorToken r;
589589

590-
if (JB_ROOT_IS_SCALAR(jb))
591-
ereport(ERROR,
592-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
593-
errmsg("cannot call %s on a scalar",
594-
JSONB"_object_keys")));
595-
else if (JB_ROOT_IS_ARRAY(jb))
596-
ereport(ERROR,
597-
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
598-
errmsg("cannot call %s on an array",
599-
JSONB"_object_keys")));
590+
if (outermost)
591+
{
592+
if (JB_ROOT_IS_SCALAR(jb))
593+
ereport(ERROR,
594+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
595+
errmsg("cannot call %s on a scalar",
596+
JSONB"_object_keys")));
597+
else if (JB_ROOT_IS_ARRAY(jb))
598+
ereport(ERROR,
599+
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
600+
errmsg("cannot call %s on an array",
601+
JSONB"_object_keys")));
602+
}
600603

601604
funcctx = SRF_FIRSTCALL_INIT();
605+
606+
if (!outermost && JB_ROOT_IS_SCALAR(jb))
607+
SRF_RETURN_DONE(funcctx);
608+
602609
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
603610

604611
state = palloc(sizeof(OkeysState));
@@ -614,7 +621,7 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
614621

615622
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
616623
{
617-
skipNested = true;
624+
skipNested = outermost;
618625

619626
if (r == WJB_KEY)
620627
{
@@ -650,6 +657,18 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
650657
SRF_RETURN_DONE(funcctx);
651658
}
652659

660+
Datum
661+
jsonb_object_keys(PG_FUNCTION_ARGS)
662+
{
663+
return jsonb_extract_keys_internal(fcinfo, true);
664+
}
665+
666+
Datum
667+
jsonb_extract_keys(PG_FUNCTION_ARGS)
668+
{
669+
return jsonb_extract_keys_internal(fcinfo, false);
670+
}
671+
653672
#ifndef JSON_C
654673
/*
655674
* Report a JSON error.

src/include/catalog/pg_proc.dat

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8511,6 +8511,9 @@
85118511
{ oid => '3957', descr => 'get json object keys',
85128512
proname => 'json_object_keys', prorows => '100', proretset => 't',
85138513
prorettype => 'text', proargtypes => 'json', prosrc => 'json_object_keys' },
8514+
{ oid => '8162', descr => 'extract all json object keys',
8515+
proname => 'json_extract_keys', prorows => '100', proretset => 't',
8516+
prorettype => 'text', proargtypes => 'json', prosrc => 'json_extract_keys' },
85148517
{ oid => '3958', descr => 'key value pairs of a json object',
85158518
proname => 'json_each', prorows => '100', proretset => 't',
85168519
prorettype => 'record', proargtypes => 'json',
@@ -9378,6 +9381,9 @@
93789381
{ oid => '3931', descr => 'get jsonb object keys',
93799382
proname => 'jsonb_object_keys', prorows => '100', proretset => 't',
93809383
prorettype => 'text', proargtypes => 'jsonb', prosrc => 'jsonb_object_keys' },
9384+
{ oid => '8161', descr => 'extract all jsonb object keys',
9385+
proname => 'jsonb_extract_keys', prorows => '100', proretset => 't',
9386+
prorettype => 'text', proargtypes => 'jsonb', prosrc => 'jsonb_extract_keys' },
93819387
{ oid => '3208', descr => 'key value pairs of a jsonb object',
93829388
proname => 'jsonb_each', prorows => '100', proretset => 't',
93839389
prorettype => 'record', proargtypes => 'jsonb',

0 commit comments

Comments
 (0)