PostgreSQL Source Code git master
jsonb.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * jsonb.c
4 * I/O routines for jsonb type
5 *
6 * Copyright (c) 2014-2025, PostgreSQL Global Development Group
7 *
8 * IDENTIFICATION
9 * src/backend/utils/adt/jsonb.c
10 *
11 *-------------------------------------------------------------------------
12 */
13#include "postgres.h"
14
15#include "access/htup_details.h"
16#include "catalog/pg_proc.h"
17#include "catalog/pg_type.h"
18#include "funcapi.h"
19#include "libpq/pqformat.h"
20#include "miscadmin.h"
21#include "utils/builtins.h"
22#include "utils/json.h"
23#include "utils/jsonb.h"
24#include "utils/jsonfuncs.h"
25#include "utils/lsyscache.h"
26#include "utils/typcache.h"
27
28typedef struct JsonbInState
29{
35
36typedef struct JsonbAggState
37{
44
45static inline Datum jsonb_from_cstring(char *json, int len, bool unique_keys,
46 Node *escontext);
47static bool checkStringLen(size_t len, Node *escontext);
48static JsonParseErrorType jsonb_in_object_start(void *pstate);
49static JsonParseErrorType jsonb_in_object_end(void *pstate);
50static JsonParseErrorType jsonb_in_array_start(void *pstate);
51static JsonParseErrorType jsonb_in_array_end(void *pstate);
52static JsonParseErrorType jsonb_in_object_field_start(void *pstate, char *fname, bool isnull);
53static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal);
54static JsonParseErrorType jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
55static void composite_to_jsonb(Datum composite, JsonbInState *result);
56static void array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims,
57 const Datum *vals, const bool *nulls, int *valcount,
58 JsonTypeCategory tcategory, Oid outfuncoid);
59static void array_to_jsonb_internal(Datum array, JsonbInState *result);
60static void datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result,
61 JsonTypeCategory tcategory, Oid outfuncoid,
62 bool key_scalar);
63static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
64 Oid val_type, bool key_scalar);
66static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
67static void add_indent(StringInfo out, bool indent, int level);
68
69/*
70 * jsonb type input function
71 */
74{
75 char *json = PG_GETARG_CSTRING(0);
76
77 return jsonb_from_cstring(json, strlen(json), false, fcinfo->context);
78}
79
80/*
81 * jsonb type recv function
82 *
83 * The type is sent as text in binary mode, so this is almost the same
84 * as the input function, but it's prefixed with a version number so we
85 * can change the binary format sent in future if necessary. For now,
86 * only version 1 is supported.
87 */
90{
92 int version = pq_getmsgint(buf, 1);
93 char *str;
94 int nbytes;
95
96 if (version == 1)
97 str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
98 else
99 elog(ERROR, "unsupported jsonb version number %d", version);
100
101 return jsonb_from_cstring(str, nbytes, false, NULL);
102}
103
104/*
105 * jsonb type output function
106 */
107Datum
109{
110 Jsonb *jb = PG_GETARG_JSONB_P(0);
111 char *out;
112
113 out = JsonbToCString(NULL, &jb->root, VARSIZE(jb));
114
116}
117
118/*
119 * jsonb type send function
120 *
121 * Just send jsonb as a version number, then a string of text
122 */
123Datum
125{
126 Jsonb *jb = PG_GETARG_JSONB_P(0);
128 StringInfo jtext = makeStringInfo();
129 int version = 1;
130
131 (void) JsonbToCString(jtext, &jb->root, VARSIZE(jb));
132
134 pq_sendint8(&buf, version);
135 pq_sendtext(&buf, jtext->data, jtext->len);
136 destroyStringInfo(jtext);
137
139}
140
141/*
142 * jsonb_from_text
143 *
144 * Turns json text string into a jsonb Datum.
145 */
146Datum
147jsonb_from_text(text *js, bool unique_keys)
148{
151 unique_keys,
152 NULL);
153}
154
155/*
156 * Get the type name of a jsonb container.
157 */
158static const char *
160{
161 JsonbValue scalar;
162
163 if (JsonbExtractScalar(jbc, &scalar))
164 return JsonbTypeName(&scalar);
165 else if (JsonContainerIsArray(jbc))
166 return "array";
167 else if (JsonContainerIsObject(jbc))
168 return "object";
169 else
170 {
171 elog(ERROR, "invalid jsonb container type: 0x%08x", jbc->header);
172 return "unknown";
173 }
174}
175
176/*
177 * Get the type name of a jsonb value.
178 */
179const char *
181{
182 switch (val->type)
183 {
184 case jbvBinary:
185 return JsonbContainerTypeName(val->val.binary.data);
186 case jbvObject:
187 return "object";
188 case jbvArray:
189 return "array";
190 case jbvNumeric:
191 return "number";
192 case jbvString:
193 return "string";
194 case jbvBool:
195 return "boolean";
196 case jbvNull:
197 return "null";
198 case jbvDatetime:
199 switch (val->val.datetime.typid)
200 {
201 case DATEOID:
202 return "date";
203 case TIMEOID:
204 return "time without time zone";
205 case TIMETZOID:
206 return "time with time zone";
207 case TIMESTAMPOID:
208 return "timestamp without time zone";
209 case TIMESTAMPTZOID:
210 return "timestamp with time zone";
211 default:
212 elog(ERROR, "unrecognized jsonb value datetime type: %d",
213 val->val.datetime.typid);
214 }
215 return "unknown";
216 default:
217 elog(ERROR, "unrecognized jsonb value type: %d", val->type);
218 return "unknown";
219 }
220}
221
222/*
223 * SQL function jsonb_typeof(jsonb) -> text
224 *
225 * This function is here because the analog json function is in json.c, since
226 * it uses the json parser internals not exposed elsewhere.
227 */
228Datum
230{
231 Jsonb *in = PG_GETARG_JSONB_P(0);
232 const char *result = JsonbContainerTypeName(&in->root);
233
235}
236
237/*
238 * jsonb_from_cstring
239 *
240 * Turns json string into a jsonb Datum.
241 *
242 * Uses the json parser (with hooks) to construct a jsonb.
243 *
244 * If escontext points to an ErrorSaveContext, errors are reported there
245 * instead of being thrown.
246 */
247static inline Datum
248jsonb_from_cstring(char *json, int len, bool unique_keys, Node *escontext)
249{
250 JsonLexContext lex;
253
254 memset(&state, 0, sizeof(state));
255 memset(&sem, 0, sizeof(sem));
257
258 state.unique_keys = unique_keys;
259 state.escontext = escontext;
260 sem.semstate = &state;
261
268
269 if (!pg_parse_json_or_errsave(&lex, &sem, escontext))
270 return (Datum) 0;
271
272 /* after parsing, the item member has the composed jsonb structure */
274}
275
276static bool
277checkStringLen(size_t len, Node *escontext)
278{
280 ereturn(escontext, false,
281 (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
282 errmsg("string too long to represent as jsonb string"),
283 errdetail("Due to an implementation restriction, jsonb strings cannot exceed %d bytes.",
285
286 return true;
287}
288
291{
292 JsonbInState *_state = (JsonbInState *) pstate;
293
294 _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
295 _state->parseState->unique_keys = _state->unique_keys;
296
297 return JSON_SUCCESS;
298}
299
302{
303 JsonbInState *_state = (JsonbInState *) pstate;
304
305 _state->res = pushJsonbValue(&_state->parseState, WJB_END_OBJECT, NULL);
306
307 return JSON_SUCCESS;
308}
309
312{
313 JsonbInState *_state = (JsonbInState *) pstate;
314
315 _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, NULL);
316
317 return JSON_SUCCESS;
318}
319
322{
323 JsonbInState *_state = (JsonbInState *) pstate;
324
325 _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
326
327 return JSON_SUCCESS;
328}
329
331jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
332{
333 JsonbInState *_state = (JsonbInState *) pstate;
334 JsonbValue v;
335
336 Assert(fname != NULL);
337 v.type = jbvString;
338 v.val.string.len = strlen(fname);
339 if (!checkStringLen(v.val.string.len, _state->escontext))
341 v.val.string.val = fname;
342
343 _state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
344
345 return JSON_SUCCESS;
346}
347
348static void
350{
351 switch (scalarVal->type)
352 {
353 case jbvNull:
354 appendBinaryStringInfo(out, "null", 4);
355 break;
356 case jbvString:
357 escape_json_with_len(out, scalarVal->val.string.val, scalarVal->val.string.len);
358 break;
359 case jbvNumeric:
362 PointerGetDatum(scalarVal->val.numeric))));
363 break;
364 case jbvBool:
365 if (scalarVal->val.boolean)
366 appendBinaryStringInfo(out, "true", 4);
367 else
368 appendBinaryStringInfo(out, "false", 5);
369 break;
370 default:
371 elog(ERROR, "unknown jsonb scalar type");
372 }
373}
374
375/*
376 * For jsonb we always want the de-escaped value - that's what's in token
377 */
379jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
380{
381 JsonbInState *_state = (JsonbInState *) pstate;
382 JsonbValue v;
383 Datum numd;
384
385 switch (tokentype)
386 {
387
389 Assert(token != NULL);
390 v.type = jbvString;
391 v.val.string.len = strlen(token);
392 if (!checkStringLen(v.val.string.len, _state->escontext))
394 v.val.string.val = token;
395 break;
397
398 /*
399 * No need to check size of numeric values, because maximum
400 * numeric size is well below the JsonbValue restriction
401 */
402 Assert(token != NULL);
403 v.type = jbvNumeric;
405 InvalidOid, -1,
406 _state->escontext,
407 &numd))
409 v.val.numeric = DatumGetNumeric(numd);
410 break;
411 case JSON_TOKEN_TRUE:
412 v.type = jbvBool;
413 v.val.boolean = true;
414 break;
415 case JSON_TOKEN_FALSE:
416 v.type = jbvBool;
417 v.val.boolean = false;
418 break;
419 case JSON_TOKEN_NULL:
420 v.type = jbvNull;
421 break;
422 default:
423 /* should not be possible */
424 elog(ERROR, "invalid json token type");
425 break;
426 }
427
428 if (_state->parseState == NULL)
429 {
430 /* single scalar */
431 JsonbValue va;
432
433 va.type = jbvArray;
434 va.val.array.rawScalar = true;
435 va.val.array.nElems = 1;
436
437 _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, &va);
438 _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
439 _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
440 }
441 else
442 {
443 JsonbValue *o = &_state->parseState->contVal;
444
445 switch (o->type)
446 {
447 case jbvArray:
448 _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
449 break;
450 case jbvObject:
451 _state->res = pushJsonbValue(&_state->parseState, WJB_VALUE, &v);
452 break;
453 default:
454 elog(ERROR, "unexpected parent of nested structure");
455 }
456 }
457
458 return JSON_SUCCESS;
459}
460
461/*
462 * JsonbToCString
463 * Converts jsonb value to a C-string.
464 *
465 * If 'out' argument is non-null, the resulting C-string is stored inside the
466 * StringBuffer. The resulting string is always returned.
467 *
468 * A typical case for passing the StringInfo in rather than NULL is where the
469 * caller wants access to the len attribute without having to call strlen, e.g.
470 * if they are converting it to a text* object.
471 */
472char *
473JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
474{
475 return JsonbToCStringWorker(out, in, estimated_len, false);
476}
477
478/*
479 * same thing but with indentation turned on
480 */
481char *
483{
484 return JsonbToCStringWorker(out, in, estimated_len, true);
485}
486
487/*
488 * common worker for above two functions
489 */
490static char *
491JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
492{
493 bool first = true;
494 JsonbIterator *it;
495 JsonbValue v;
497 int level = 0;
498 bool redo_switch = false;
499
500 /* If we are indenting, don't add a space after a comma */
501 int ispaces = indent ? 1 : 2;
502
503 /*
504 * Don't indent the very first item. This gets set to the indent flag at
505 * the bottom of the loop.
506 */
507 bool use_indent = false;
508 bool raw_scalar = false;
509 bool last_was_key = false;
510
511 if (out == NULL)
512 out = makeStringInfo();
513
514 enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);
515
516 it = JsonbIteratorInit(in);
517
518 while (redo_switch ||
519 ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
520 {
521 redo_switch = false;
522 switch (type)
523 {
524 case WJB_BEGIN_ARRAY:
525 if (!first)
526 appendBinaryStringInfo(out, ", ", ispaces);
527
528 if (!v.val.array.rawScalar)
529 {
530 add_indent(out, use_indent && !last_was_key, level);
532 }
533 else
534 raw_scalar = true;
535
536 first = true;
537 level++;
538 break;
539 case WJB_BEGIN_OBJECT:
540 if (!first)
541 appendBinaryStringInfo(out, ", ", ispaces);
542
543 add_indent(out, use_indent && !last_was_key, level);
545
546 first = true;
547 level++;
548 break;
549 case WJB_KEY:
550 if (!first)
551 appendBinaryStringInfo(out, ", ", ispaces);
552 first = true;
553
554 add_indent(out, use_indent, level);
555
556 /* json rules guarantee this is a string */
558 appendBinaryStringInfo(out, ": ", 2);
559
560 type = JsonbIteratorNext(&it, &v, false);
561 if (type == WJB_VALUE)
562 {
563 first = false;
565 }
566 else
567 {
569
570 /*
571 * We need to rerun the current switch() since we need to
572 * output the object which we just got from the iterator
573 * before calling the iterator again.
574 */
575 redo_switch = true;
576 }
577 break;
578 case WJB_ELEM:
579 if (!first)
580 appendBinaryStringInfo(out, ", ", ispaces);
581 first = false;
582
583 if (!raw_scalar)
584 add_indent(out, use_indent, level);
586 break;
587 case WJB_END_ARRAY:
588 level--;
589 if (!raw_scalar)
590 {
591 add_indent(out, use_indent, level);
593 }
594 first = false;
595 break;
596 case WJB_END_OBJECT:
597 level--;
598 add_indent(out, use_indent, level);
600 first = false;
601 break;
602 default:
603 elog(ERROR, "unknown jsonb iterator token type");
604 }
605 use_indent = indent;
606 last_was_key = redo_switch;
607 }
608
609 Assert(level == 0);
610
611 return out->data;
612}
613
614static void
615add_indent(StringInfo out, bool indent, int level)
616{
617 if (indent)
618 {
619 appendStringInfoCharMacro(out, '\n');
620 appendStringInfoSpaces(out, level * 4);
621 }
622}
623
624
625/*
626 * Turn a Datum into jsonb, adding it to the result JsonbInState.
627 *
628 * tcategory and outfuncoid are from a previous call to json_categorize_type,
629 * except that if is_null is true then they can be invalid.
630 *
631 * If key_scalar is true, the value is stored as a key, so insist
632 * it's of an acceptable type, and force it to be a jbvString.
633 *
634 * Note: currently, we assume that result->escontext is NULL and errors
635 * will be thrown.
636 */
637static void
639 JsonTypeCategory tcategory, Oid outfuncoid,
640 bool key_scalar)
641{
642 char *outputstr;
643 bool numeric_error;
644 JsonbValue jb;
645 bool scalar_jsonb = false;
646
648
649 /* Convert val to a JsonbValue in jb (in most cases) */
650 if (is_null)
651 {
652 Assert(!key_scalar);
653 jb.type = jbvNull;
654 }
655 else if (key_scalar &&
656 (tcategory == JSONTYPE_ARRAY ||
657 tcategory == JSONTYPE_COMPOSITE ||
658 tcategory == JSONTYPE_JSON ||
659 tcategory == JSONTYPE_JSONB ||
660 tcategory == JSONTYPE_JSON))
661 {
663 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
664 errmsg("key value must be scalar, not array, composite, or json")));
665 }
666 else
667 {
668 if (tcategory == JSONTYPE_CAST)
669 val = OidFunctionCall1(outfuncoid, val);
670
671 switch (tcategory)
672 {
673 case JSONTYPE_ARRAY:
675 break;
677 composite_to_jsonb(val, result);
678 break;
679 case JSONTYPE_BOOL:
680 if (key_scalar)
681 {
682 outputstr = DatumGetBool(val) ? "true" : "false";
683 jb.type = jbvString;
684 jb.val.string.len = strlen(outputstr);
685 jb.val.string.val = outputstr;
686 }
687 else
688 {
689 jb.type = jbvBool;
690 jb.val.boolean = DatumGetBool(val);
691 }
692 break;
693 case JSONTYPE_NUMERIC:
694 outputstr = OidOutputFunctionCall(outfuncoid, val);
695 if (key_scalar)
696 {
697 /* always quote keys */
698 jb.type = jbvString;
699 jb.val.string.len = strlen(outputstr);
700 jb.val.string.val = outputstr;
701 }
702 else
703 {
704 /*
705 * Make it numeric if it's a valid JSON number, otherwise
706 * a string. Invalid numeric output will always have an
707 * 'N' or 'n' in it (I think).
708 */
709 numeric_error = (strchr(outputstr, 'N') != NULL ||
710 strchr(outputstr, 'n') != NULL);
711 if (!numeric_error)
712 {
713 Datum numd;
714
715 jb.type = jbvNumeric;
717 CStringGetDatum(outputstr),
719 Int32GetDatum(-1));
720 jb.val.numeric = DatumGetNumeric(numd);
721 pfree(outputstr);
722 }
723 else
724 {
725 jb.type = jbvString;
726 jb.val.string.len = strlen(outputstr);
727 jb.val.string.val = outputstr;
728 }
729 }
730 break;
731 case JSONTYPE_DATE:
732 jb.type = jbvString;
733 jb.val.string.val = JsonEncodeDateTime(NULL, val,
734 DATEOID, NULL);
735 jb.val.string.len = strlen(jb.val.string.val);
736 break;
738 jb.type = jbvString;
739 jb.val.string.val = JsonEncodeDateTime(NULL, val,
740 TIMESTAMPOID, NULL);
741 jb.val.string.len = strlen(jb.val.string.val);
742 break;
744 jb.type = jbvString;
745 jb.val.string.val = JsonEncodeDateTime(NULL, val,
746 TIMESTAMPTZOID, NULL);
747 jb.val.string.len = strlen(jb.val.string.val);
748 break;
749 case JSONTYPE_CAST:
750 case JSONTYPE_JSON:
751 {
752 /* parse the json right into the existing result object */
753 JsonLexContext lex;
755 text *json = DatumGetTextPP(val);
756
757 makeJsonLexContext(&lex, json, true);
758
759 memset(&sem, 0, sizeof(sem));
760
761 sem.semstate = result;
762
769
771 freeJsonLexContext(&lex);
772 }
773 break;
774 case JSONTYPE_JSONB:
775 {
776 Jsonb *jsonb = DatumGetJsonbP(val);
777 JsonbIterator *it;
778
779 it = JsonbIteratorInit(&jsonb->root);
780
781 if (JB_ROOT_IS_SCALAR(jsonb))
782 {
783 (void) JsonbIteratorNext(&it, &jb, true);
784 Assert(jb.type == jbvArray);
785 (void) JsonbIteratorNext(&it, &jb, true);
786 scalar_jsonb = true;
787 }
788 else
789 {
791
792 while ((type = JsonbIteratorNext(&it, &jb, false))
793 != WJB_DONE)
794 {
795 if (type == WJB_END_ARRAY || type == WJB_END_OBJECT ||
797 result->res = pushJsonbValue(&result->parseState,
798 type, NULL);
799 else
800 result->res = pushJsonbValue(&result->parseState,
801 type, &jb);
802 }
803 }
804 }
805 break;
806 default:
807 outputstr = OidOutputFunctionCall(outfuncoid, val);
808 jb.type = jbvString;
809 jb.val.string.len = strlen(outputstr);
810 (void) checkStringLen(jb.val.string.len, NULL);
811 jb.val.string.val = outputstr;
812 break;
813 }
814 }
815
816 /* Now insert jb into result, unless we did it recursively */
817 if (!is_null && !scalar_jsonb &&
818 tcategory >= JSONTYPE_JSON && tcategory <= JSONTYPE_CAST)
819 {
820 /* work has been done recursively */
821 return;
822 }
823 else if (result->parseState == NULL)
824 {
825 /* single root scalar */
826 JsonbValue va;
827
828 va.type = jbvArray;
829 va.val.array.rawScalar = true;
830 va.val.array.nElems = 1;
831
832 result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, &va);
833 result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
834 result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
835 }
836 else
837 {
838 JsonbValue *o = &result->parseState->contVal;
839
840 switch (o->type)
841 {
842 case jbvArray:
843 result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
844 break;
845 case jbvObject:
846 result->res = pushJsonbValue(&result->parseState,
847 key_scalar ? WJB_KEY : WJB_VALUE,
848 &jb);
849 break;
850 default:
851 elog(ERROR, "unexpected parent of nested structure");
852 }
853 }
854}
855
856/*
857 * Process a single dimension of an array.
858 * If it's the innermost dimension, output the values, otherwise call
859 * ourselves recursively to process the next dimension.
860 */
861static void
862array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, const Datum *vals,
863 const bool *nulls, int *valcount, JsonTypeCategory tcategory,
864 Oid outfuncoid)
865{
866 int i;
867
868 Assert(dim < ndims);
869
870 result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
871
872 for (i = 1; i <= dims[dim]; i++)
873 {
874 if (dim + 1 == ndims)
875 {
876 datum_to_jsonb_internal(vals[*valcount], nulls[*valcount], result, tcategory,
877 outfuncoid, false);
878 (*valcount)++;
879 }
880 else
881 {
882 array_dim_to_jsonb(result, dim + 1, ndims, dims, vals, nulls,
883 valcount, tcategory, outfuncoid);
884 }
885 }
886
887 result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
888}
889
890/*
891 * Turn an array into JSON.
892 */
893static void
895{
896 ArrayType *v = DatumGetArrayTypeP(array);
897 Oid element_type = ARR_ELEMTYPE(v);
898 int *dim;
899 int ndim;
900 int nitems;
901 int count = 0;
902 Datum *elements;
903 bool *nulls;
904 int16 typlen;
905 bool typbyval;
906 char typalign;
907 JsonTypeCategory tcategory;
908 Oid outfuncoid;
909
910 ndim = ARR_NDIM(v);
911 dim = ARR_DIMS(v);
912 nitems = ArrayGetNItems(ndim, dim);
913
914 if (nitems <= 0)
915 {
916 result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
917 result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
918 return;
919 }
920
921 get_typlenbyvalalign(element_type,
922 &typlen, &typbyval, &typalign);
923
924 json_categorize_type(element_type, true,
925 &tcategory, &outfuncoid);
926
927 deconstruct_array(v, element_type, typlen, typbyval,
928 typalign, &elements, &nulls,
929 &nitems);
930
931 array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory,
932 outfuncoid);
933
934 pfree(elements);
935 pfree(nulls);
936}
937
938/*
939 * Turn a composite / record into JSON.
940 */
941static void
943{
945 Oid tupType;
946 int32 tupTypmod;
947 TupleDesc tupdesc;
948 HeapTupleData tmptup,
949 *tuple;
950 int i;
951
952 td = DatumGetHeapTupleHeader(composite);
953
954 /* Extract rowtype info and find a tupdesc */
955 tupType = HeapTupleHeaderGetTypeId(td);
956 tupTypmod = HeapTupleHeaderGetTypMod(td);
957 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
958
959 /* Build a temporary HeapTuple control structure */
961 tmptup.t_data = td;
962 tuple = &tmptup;
963
964 result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_OBJECT, NULL);
965
966 for (i = 0; i < tupdesc->natts; i++)
967 {
968 Datum val;
969 bool isnull;
970 char *attname;
971 JsonTypeCategory tcategory;
972 Oid outfuncoid;
973 JsonbValue v;
974 Form_pg_attribute att = TupleDescAttr(tupdesc, i);
975
976 if (att->attisdropped)
977 continue;
978
979 attname = NameStr(att->attname);
980
981 v.type = jbvString;
982 /* don't need checkStringLen here - can't exceed maximum name length */
983 v.val.string.len = strlen(attname);
984 v.val.string.val = attname;
985
986 result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
987
988 val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
989
990 if (isnull)
991 {
992 tcategory = JSONTYPE_NULL;
993 outfuncoid = InvalidOid;
994 }
995 else
996 json_categorize_type(att->atttypid, true, &tcategory,
997 &outfuncoid);
998
999 datum_to_jsonb_internal(val, isnull, result, tcategory, outfuncoid,
1000 false);
1001 }
1002
1003 result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
1004 ReleaseTupleDesc(tupdesc);
1005}
1006
1007/*
1008 * Append JSON text for "val" to "result".
1009 *
1010 * This is just a thin wrapper around datum_to_jsonb. If the same type will be
1011 * printed many times, avoid using this; better to do the json_categorize_type
1012 * lookups only once.
1013 */
1014
1015static void
1016add_jsonb(Datum val, bool is_null, JsonbInState *result,
1017 Oid val_type, bool key_scalar)
1018{
1019 JsonTypeCategory tcategory;
1020 Oid outfuncoid;
1021
1022 if (val_type == InvalidOid)
1023 ereport(ERROR,
1024 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1025 errmsg("could not determine input data type")));
1026
1027 if (is_null)
1028 {
1029 tcategory = JSONTYPE_NULL;
1030 outfuncoid = InvalidOid;
1031 }
1032 else
1033 json_categorize_type(val_type, true,
1034 &tcategory, &outfuncoid);
1035
1036 datum_to_jsonb_internal(val, is_null, result, tcategory, outfuncoid,
1037 key_scalar);
1038}
1039
1040
1041/*
1042 * Is the given type immutable when coming out of a JSONB context?
1043 *
1044 * At present, datetimes are all considered mutable, because they
1045 * depend on timezone. XXX we should also drill down into objects and
1046 * arrays, but do not.
1047 */
1048bool
1050{
1051 JsonTypeCategory tcategory;
1052 Oid outfuncoid;
1053
1054 json_categorize_type(typoid, true, &tcategory, &outfuncoid);
1055
1056 switch (tcategory)
1057 {
1058 case JSONTYPE_NULL:
1059 case JSONTYPE_BOOL:
1060 case JSONTYPE_JSON:
1061 case JSONTYPE_JSONB:
1062 return true;
1063
1064 case JSONTYPE_DATE:
1065 case JSONTYPE_TIMESTAMP:
1067 return false;
1068
1069 case JSONTYPE_ARRAY:
1070 return false; /* TODO recurse into elements */
1071
1072 case JSONTYPE_COMPOSITE:
1073 return false; /* TODO recurse into fields */
1074
1075 case JSONTYPE_NUMERIC:
1076 case JSONTYPE_CAST:
1077 case JSONTYPE_OTHER:
1078 return func_volatile(outfuncoid) == PROVOLATILE_IMMUTABLE;
1079 }
1080
1081 return false; /* not reached */
1082}
1083
1084/*
1085 * SQL function to_jsonb(anyvalue)
1086 */
1087Datum
1089{
1091 Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
1092 JsonTypeCategory tcategory;
1093 Oid outfuncoid;
1094
1095 if (val_type == InvalidOid)
1096 ereport(ERROR,
1097 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1098 errmsg("could not determine input data type")));
1099
1100 json_categorize_type(val_type, true,
1101 &tcategory, &outfuncoid);
1102
1103 PG_RETURN_DATUM(datum_to_jsonb(val, tcategory, outfuncoid));
1104}
1105
1106/*
1107 * Turn a Datum into jsonb.
1108 *
1109 * tcategory and outfuncoid are from a previous call to json_categorize_type.
1110 */
1111Datum
1113{
1114 JsonbInState result;
1115
1116 memset(&result, 0, sizeof(JsonbInState));
1117
1118 datum_to_jsonb_internal(val, false, &result, tcategory, outfuncoid,
1119 false);
1120
1121 return JsonbPGetDatum(JsonbValueToJsonb(result.res));
1122}
1123
1124Datum
1125jsonb_build_object_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types,
1126 bool absent_on_null, bool unique_keys)
1127{
1128 int i;
1129 JsonbInState result;
1130
1131 if (nargs % 2 != 0)
1132 ereport(ERROR,
1133 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1134 errmsg("argument list must have even number of elements"),
1135 /* translator: %s is a SQL function name */
1136 errhint("The arguments of %s must consist of alternating keys and values.",
1137 "jsonb_build_object()")));
1138
1139 memset(&result, 0, sizeof(JsonbInState));
1140
1141 result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1142 result.parseState->unique_keys = unique_keys;
1143 result.parseState->skip_nulls = absent_on_null;
1144
1145 for (i = 0; i < nargs; i += 2)
1146 {
1147 /* process key */
1148 bool skip;
1149
1150 if (nulls[i])
1151 ereport(ERROR,
1152 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1153 errmsg("argument %d: key must not be null", i + 1)));
1154
1155 /* skip null values if absent_on_null */
1156 skip = absent_on_null && nulls[i + 1];
1157
1158 /* we need to save skipped keys for the key uniqueness check */
1159 if (skip && !unique_keys)
1160 continue;
1161
1162 add_jsonb(args[i], false, &result, types[i], true);
1163
1164 /* process value */
1165 add_jsonb(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
1166 }
1167
1168 result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1169
1170 return JsonbPGetDatum(JsonbValueToJsonb(result.res));
1171}
1172
1173/*
1174 * SQL function jsonb_build_object(variadic "any")
1175 */
1176Datum
1178{
1179 Datum *args;
1180 bool *nulls;
1181 Oid *types;
1182
1183 /* build argument values to build the object */
1184 int nargs = extract_variadic_args(fcinfo, 0, true,
1185 &args, &types, &nulls);
1186
1187 if (nargs < 0)
1189
1190 PG_RETURN_DATUM(jsonb_build_object_worker(nargs, args, nulls, types, false, false));
1191}
1192
1193/*
1194 * degenerate case of jsonb_build_object where it gets 0 arguments.
1195 */
1196Datum
1198{
1199 JsonbInState result;
1200
1201 memset(&result, 0, sizeof(JsonbInState));
1202
1203 (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1204 result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1205
1207}
1208
1209Datum
1210jsonb_build_array_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types,
1211 bool absent_on_null)
1212{
1213 int i;
1214 JsonbInState result;
1215
1216 memset(&result, 0, sizeof(JsonbInState));
1217
1218 result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1219
1220 for (i = 0; i < nargs; i++)
1221 {
1222 if (absent_on_null && nulls[i])
1223 continue;
1224
1225 add_jsonb(args[i], nulls[i], &result, types[i], false);
1226 }
1227
1228 result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1229
1230 return JsonbPGetDatum(JsonbValueToJsonb(result.res));
1231}
1232
1233/*
1234 * SQL function jsonb_build_array(variadic "any")
1235 */
1236Datum
1238{
1239 Datum *args;
1240 bool *nulls;
1241 Oid *types;
1242
1243 /* build argument values to build the object */
1244 int nargs = extract_variadic_args(fcinfo, 0, true,
1245 &args, &types, &nulls);
1246
1247 if (nargs < 0)
1249
1250 PG_RETURN_DATUM(jsonb_build_array_worker(nargs, args, nulls, types, false));
1251}
1252
1253
1254/*
1255 * degenerate case of jsonb_build_array where it gets 0 arguments.
1256 */
1257Datum
1259{
1260 JsonbInState result;
1261
1262 memset(&result, 0, sizeof(JsonbInState));
1263
1264 (void) pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1265 result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1266
1268}
1269
1270
1271/*
1272 * SQL function jsonb_object(text[])
1273 *
1274 * take a one or two dimensional array of text as name value pairs
1275 * for a jsonb object.
1276 *
1277 */
1278Datum
1280{
1281 ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1282 int ndims = ARR_NDIM(in_array);
1283 Datum *in_datums;
1284 bool *in_nulls;
1285 int in_count,
1286 count,
1287 i;
1288 JsonbInState result;
1289
1290 memset(&result, 0, sizeof(JsonbInState));
1291
1292 (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1293
1294 switch (ndims)
1295 {
1296 case 0:
1297 goto close_object;
1298 break;
1299
1300 case 1:
1301 if ((ARR_DIMS(in_array)[0]) % 2)
1302 ereport(ERROR,
1303 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1304 errmsg("array must have even number of elements")));
1305 break;
1306
1307 case 2:
1308 if ((ARR_DIMS(in_array)[1]) != 2)
1309 ereport(ERROR,
1310 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1311 errmsg("array must have two columns")));
1312 break;
1313
1314 default:
1315 ereport(ERROR,
1316 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1317 errmsg("wrong number of array subscripts")));
1318 }
1319
1320 deconstruct_array_builtin(in_array, TEXTOID, &in_datums, &in_nulls, &in_count);
1321
1322 count = in_count / 2;
1323
1324 for (i = 0; i < count; ++i)
1325 {
1326 JsonbValue v;
1327 char *str;
1328 int len;
1329
1330 if (in_nulls[i * 2])
1331 ereport(ERROR,
1332 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1333 errmsg("null value not allowed for object key")));
1334
1335 str = TextDatumGetCString(in_datums[i * 2]);
1336 len = strlen(str);
1337
1338 v.type = jbvString;
1339
1340 v.val.string.len = len;
1341 v.val.string.val = str;
1342
1343 (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1344
1345 if (in_nulls[i * 2 + 1])
1346 {
1347 v.type = jbvNull;
1348 }
1349 else
1350 {
1351 str = TextDatumGetCString(in_datums[i * 2 + 1]);
1352 len = strlen(str);
1353
1354 v.type = jbvString;
1355
1356 v.val.string.len = len;
1357 v.val.string.val = str;
1358 }
1359
1360 (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1361 }
1362
1363 pfree(in_datums);
1364 pfree(in_nulls);
1365
1366close_object:
1367 result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1368
1370}
1371
1372/*
1373 * SQL function jsonb_object(text[], text[])
1374 *
1375 * take separate name and value arrays of text to construct a jsonb object
1376 * pairwise.
1377 */
1378Datum
1380{
1381 ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1382 ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1383 int nkdims = ARR_NDIM(key_array);
1384 int nvdims = ARR_NDIM(val_array);
1385 Datum *key_datums,
1386 *val_datums;
1387 bool *key_nulls,
1388 *val_nulls;
1389 int key_count,
1390 val_count,
1391 i;
1392 JsonbInState result;
1393
1394 memset(&result, 0, sizeof(JsonbInState));
1395
1396 (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1397
1398 if (nkdims > 1 || nkdims != nvdims)
1399 ereport(ERROR,
1400 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1401 errmsg("wrong number of array subscripts")));
1402
1403 if (nkdims == 0)
1404 goto close_object;
1405
1406 deconstruct_array_builtin(key_array, TEXTOID, &key_datums, &key_nulls, &key_count);
1407 deconstruct_array_builtin(val_array, TEXTOID, &val_datums, &val_nulls, &val_count);
1408
1409 if (key_count != val_count)
1410 ereport(ERROR,
1411 (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1412 errmsg("mismatched array dimensions")));
1413
1414 for (i = 0; i < key_count; ++i)
1415 {
1416 JsonbValue v;
1417 char *str;
1418 int len;
1419
1420 if (key_nulls[i])
1421 ereport(ERROR,
1422 (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1423 errmsg("null value not allowed for object key")));
1424
1425 str = TextDatumGetCString(key_datums[i]);
1426 len = strlen(str);
1427
1428 v.type = jbvString;
1429
1430 v.val.string.len = len;
1431 v.val.string.val = str;
1432
1433 (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1434
1435 if (val_nulls[i])
1436 {
1437 v.type = jbvNull;
1438 }
1439 else
1440 {
1441 str = TextDatumGetCString(val_datums[i]);
1442 len = strlen(str);
1443
1444 v.type = jbvString;
1445
1446 v.val.string.len = len;
1447 v.val.string.val = str;
1448 }
1449
1450 (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1451 }
1452
1453 pfree(key_datums);
1454 pfree(key_nulls);
1455 pfree(val_datums);
1456 pfree(val_nulls);
1457
1458close_object:
1459 result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1460
1462}
1463
1464
1465/*
1466 * shallow clone of a parse state, suitable for use in aggregate
1467 * final functions that will only append to the values rather than
1468 * change them.
1469 */
1470static JsonbParseState *
1472{
1473 JsonbParseState *result,
1474 *icursor,
1475 *ocursor;
1476
1477 if (state == NULL)
1478 return NULL;
1479
1480 result = palloc(sizeof(JsonbParseState));
1481 icursor = state;
1482 ocursor = result;
1483 for (;;)
1484 {
1485 ocursor->contVal = icursor->contVal;
1486 ocursor->size = icursor->size;
1487 ocursor->unique_keys = icursor->unique_keys;
1488 ocursor->skip_nulls = icursor->skip_nulls;
1489 icursor = icursor->next;
1490 if (icursor == NULL)
1491 break;
1492 ocursor->next = palloc(sizeof(JsonbParseState));
1493 ocursor = ocursor->next;
1494 }
1495 ocursor->next = NULL;
1496
1497 return result;
1498}
1499
1500static Datum
1501jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
1502{
1503 MemoryContext oldcontext,
1504 aggcontext;
1506 JsonbInState elem;
1507 Datum val;
1508 JsonbInState *result;
1509 bool single_scalar = false;
1510 JsonbIterator *it;
1511 Jsonb *jbelem;
1512 JsonbValue v;
1514
1515 if (!AggCheckCallContext(fcinfo, &aggcontext))
1516 {
1517 /* cannot be called directly because of internal-type argument */
1518 elog(ERROR, "jsonb_agg_transfn called in non-aggregate context");
1519 }
1520
1521 /* set up the accumulator on the first go round */
1522
1523 if (PG_ARGISNULL(0))
1524 {
1525 Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1526
1527 if (arg_type == InvalidOid)
1528 ereport(ERROR,
1529 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1530 errmsg("could not determine input data type")));
1531
1532 oldcontext = MemoryContextSwitchTo(aggcontext);
1533 state = palloc(sizeof(JsonbAggState));
1534 result = palloc0(sizeof(JsonbInState));
1535 state->res = result;
1536 result->res = pushJsonbValue(&result->parseState,
1537 WJB_BEGIN_ARRAY, NULL);
1538 MemoryContextSwitchTo(oldcontext);
1539
1540 json_categorize_type(arg_type, true, &state->val_category,
1541 &state->val_output_func);
1542 }
1543 else
1544 {
1546 result = state->res;
1547 }
1548
1549 if (absent_on_null && PG_ARGISNULL(1))
1551
1552 /* turn the argument into jsonb in the normal function context */
1553
1554 val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
1555
1556 memset(&elem, 0, sizeof(JsonbInState));
1557
1558 datum_to_jsonb_internal(val, PG_ARGISNULL(1), &elem, state->val_category,
1559 state->val_output_func, false);
1560
1561 jbelem = JsonbValueToJsonb(elem.res);
1562
1563 /* switch to the aggregate context for accumulation operations */
1564
1565 oldcontext = MemoryContextSwitchTo(aggcontext);
1566
1567 it = JsonbIteratorInit(&jbelem->root);
1568
1569 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1570 {
1571 switch (type)
1572 {
1573 case WJB_BEGIN_ARRAY:
1574 if (v.val.array.rawScalar)
1575 single_scalar = true;
1576 else
1577 result->res = pushJsonbValue(&result->parseState,
1578 type, NULL);
1579 break;
1580 case WJB_END_ARRAY:
1581 if (!single_scalar)
1582 result->res = pushJsonbValue(&result->parseState,
1583 type, NULL);
1584 break;
1585 case WJB_BEGIN_OBJECT:
1586 case WJB_END_OBJECT:
1587 result->res = pushJsonbValue(&result->parseState,
1588 type, NULL);
1589 break;
1590 case WJB_ELEM:
1591 case WJB_KEY:
1592 case WJB_VALUE:
1593 if (v.type == jbvString)
1594 {
1595 /* copy string values in the aggregate context */
1596 char *buf = palloc(v.val.string.len + 1);
1597
1598 snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1599 v.val.string.val = buf;
1600 }
1601 else if (v.type == jbvNumeric)
1602 {
1603 /* same for numeric */
1604 v.val.numeric =
1606 NumericGetDatum(v.val.numeric)));
1607 }
1608 result->res = pushJsonbValue(&result->parseState,
1609 type, &v);
1610 break;
1611 default:
1612 elog(ERROR, "unknown jsonb iterator token type");
1613 }
1614 }
1615
1616 MemoryContextSwitchTo(oldcontext);
1617
1619}
1620
1621/*
1622 * jsonb_agg aggregate function
1623 */
1624Datum
1626{
1627 return jsonb_agg_transfn_worker(fcinfo, false);
1628}
1629
1630/*
1631 * jsonb_agg_strict aggregate function
1632 */
1633Datum
1635{
1636 return jsonb_agg_transfn_worker(fcinfo, true);
1637}
1638
1639Datum
1641{
1643 JsonbInState result;
1644 Jsonb *out;
1645
1646 /* cannot be called directly because of internal-type argument */
1647 Assert(AggCheckCallContext(fcinfo, NULL));
1648
1649 if (PG_ARGISNULL(0))
1650 PG_RETURN_NULL(); /* returns null iff no input values */
1651
1653
1654 /*
1655 * We need to do a shallow clone of the argument in case the final
1656 * function is called more than once, so we avoid changing the argument. A
1657 * shallow clone is sufficient as we aren't going to change any of the
1658 * values, just add the final array end marker.
1659 */
1660 memset(&result, 0, sizeof(JsonbInState));
1661
1662 result.parseState = clone_parse_state(arg->res->parseState);
1663
1664 result.res = pushJsonbValue(&result.parseState,
1665 WJB_END_ARRAY, NULL);
1666
1667 out = JsonbValueToJsonb(result.res);
1668
1669 PG_RETURN_POINTER(out);
1670}
1671
1672static Datum
1674 bool absent_on_null, bool unique_keys)
1675{
1676 MemoryContext oldcontext,
1677 aggcontext;
1678 JsonbInState elem;
1680 Datum val;
1681 JsonbInState *result;
1682 bool single_scalar;
1683 JsonbIterator *it;
1684 Jsonb *jbkey,
1685 *jbval;
1686 JsonbValue v;
1688 bool skip;
1689
1690 if (!AggCheckCallContext(fcinfo, &aggcontext))
1691 {
1692 /* cannot be called directly because of internal-type argument */
1693 elog(ERROR, "jsonb_object_agg_transfn called in non-aggregate context");
1694 }
1695
1696 /* set up the accumulator on the first go round */
1697
1698 if (PG_ARGISNULL(0))
1699 {
1700 Oid arg_type;
1701
1702 oldcontext = MemoryContextSwitchTo(aggcontext);
1703 state = palloc(sizeof(JsonbAggState));
1704 result = palloc0(sizeof(JsonbInState));
1705 state->res = result;
1706 result->res = pushJsonbValue(&result->parseState,
1707 WJB_BEGIN_OBJECT, NULL);
1708 result->parseState->unique_keys = unique_keys;
1709 result->parseState->skip_nulls = absent_on_null;
1710
1711 MemoryContextSwitchTo(oldcontext);
1712
1713 arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1714
1715 if (arg_type == InvalidOid)
1716 ereport(ERROR,
1717 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1718 errmsg("could not determine input data type")));
1719
1720 json_categorize_type(arg_type, true, &state->key_category,
1721 &state->key_output_func);
1722
1723 arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1724
1725 if (arg_type == InvalidOid)
1726 ereport(ERROR,
1727 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1728 errmsg("could not determine input data type")));
1729
1730 json_categorize_type(arg_type, true, &state->val_category,
1731 &state->val_output_func);
1732 }
1733 else
1734 {
1736 result = state->res;
1737 }
1738
1739 /* turn the argument into jsonb in the normal function context */
1740
1741 if (PG_ARGISNULL(1))
1742 ereport(ERROR,
1743 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1744 errmsg("field name must not be null")));
1745
1746 /*
1747 * Skip null values if absent_on_null unless key uniqueness check is
1748 * needed (because we must save keys in this case).
1749 */
1750 skip = absent_on_null && PG_ARGISNULL(2);
1751
1752 if (skip && !unique_keys)
1754
1755 val = PG_GETARG_DATUM(1);
1756
1757 memset(&elem, 0, sizeof(JsonbInState));
1758
1759 datum_to_jsonb_internal(val, false, &elem, state->key_category,
1760 state->key_output_func, true);
1761
1762 jbkey = JsonbValueToJsonb(elem.res);
1763
1764 val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
1765
1766 memset(&elem, 0, sizeof(JsonbInState));
1767
1768 datum_to_jsonb_internal(val, PG_ARGISNULL(2), &elem, state->val_category,
1769 state->val_output_func, false);
1770
1771 jbval = JsonbValueToJsonb(elem.res);
1772
1773 it = JsonbIteratorInit(&jbkey->root);
1774
1775 /* switch to the aggregate context for accumulation operations */
1776
1777 oldcontext = MemoryContextSwitchTo(aggcontext);
1778
1779 /*
1780 * keys should be scalar, and we should have already checked for that
1781 * above when calling datum_to_jsonb, so we only need to look for these
1782 * things.
1783 */
1784
1785 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1786 {
1787 switch (type)
1788 {
1789 case WJB_BEGIN_ARRAY:
1790 if (!v.val.array.rawScalar)
1791 elog(ERROR, "unexpected structure for key");
1792 break;
1793 case WJB_ELEM:
1794 if (v.type == jbvString)
1795 {
1796 /* copy string values in the aggregate context */
1797 char *buf = palloc(v.val.string.len + 1);
1798
1799 snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1800 v.val.string.val = buf;
1801 }
1802 else
1803 {
1804 ereport(ERROR,
1805 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1806 errmsg("object keys must be strings")));
1807 }
1808 result->res = pushJsonbValue(&result->parseState,
1809 WJB_KEY, &v);
1810
1811 if (skip)
1812 {
1813 v.type = jbvNull;
1814 result->res = pushJsonbValue(&result->parseState,
1815 WJB_VALUE, &v);
1816 MemoryContextSwitchTo(oldcontext);
1818 }
1819
1820 break;
1821 case WJB_END_ARRAY:
1822 break;
1823 default:
1824 elog(ERROR, "unexpected structure for key");
1825 break;
1826 }
1827 }
1828
1829 it = JsonbIteratorInit(&jbval->root);
1830
1831 single_scalar = false;
1832
1833 /*
1834 * values can be anything, including structured and null, so we treat them
1835 * as in json_agg_transfn, except that single scalars are always pushed as
1836 * WJB_VALUE items.
1837 */
1838
1839 while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1840 {
1841 switch (type)
1842 {
1843 case WJB_BEGIN_ARRAY:
1844 if (v.val.array.rawScalar)
1845 single_scalar = true;
1846 else
1847 result->res = pushJsonbValue(&result->parseState,
1848 type, NULL);
1849 break;
1850 case WJB_END_ARRAY:
1851 if (!single_scalar)
1852 result->res = pushJsonbValue(&result->parseState,
1853 type, NULL);
1854 break;
1855 case WJB_BEGIN_OBJECT:
1856 case WJB_END_OBJECT:
1857 result->res = pushJsonbValue(&result->parseState,
1858 type, NULL);
1859 break;
1860 case WJB_ELEM:
1861 case WJB_KEY:
1862 case WJB_VALUE:
1863 if (v.type == jbvString)
1864 {
1865 /* copy string values in the aggregate context */
1866 char *buf = palloc(v.val.string.len + 1);
1867
1868 snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1869 v.val.string.val = buf;
1870 }
1871 else if (v.type == jbvNumeric)
1872 {
1873 /* same for numeric */
1874 v.val.numeric =
1876 NumericGetDatum(v.val.numeric)));
1877 }
1878 result->res = pushJsonbValue(&result->parseState,
1879 single_scalar ? WJB_VALUE : type,
1880 &v);
1881 break;
1882 default:
1883 elog(ERROR, "unknown jsonb iterator token type");
1884 }
1885 }
1886
1887 MemoryContextSwitchTo(oldcontext);
1888
1890}
1891
1892/*
1893 * jsonb_object_agg aggregate function
1894 */
1895Datum
1897{
1898 return jsonb_object_agg_transfn_worker(fcinfo, false, false);
1899}
1900
1901
1902/*
1903 * jsonb_object_agg_strict aggregate function
1904 */
1905Datum
1907{
1908 return jsonb_object_agg_transfn_worker(fcinfo, true, false);
1909}
1910
1911/*
1912 * jsonb_object_agg_unique aggregate function
1913 */
1914Datum
1916{
1917 return jsonb_object_agg_transfn_worker(fcinfo, false, true);
1918}
1919
1920/*
1921 * jsonb_object_agg_unique_strict aggregate function
1922 */
1923Datum
1925{
1926 return jsonb_object_agg_transfn_worker(fcinfo, true, true);
1927}
1928
1929Datum
1931{
1933 JsonbInState result;
1934 Jsonb *out;
1935
1936 /* cannot be called directly because of internal-type argument */
1937 Assert(AggCheckCallContext(fcinfo, NULL));
1938
1939 if (PG_ARGISNULL(0))
1940 PG_RETURN_NULL(); /* returns null iff no input values */
1941
1943
1944 /*
1945 * We need to do a shallow clone of the argument's res field in case the
1946 * final function is called more than once, so we avoid changing the
1947 * aggregate state value. A shallow clone is sufficient as we aren't
1948 * going to change any of the values, just add the final object end
1949 * marker.
1950 */
1951 memset(&result, 0, sizeof(JsonbInState));
1952
1953 result.parseState = clone_parse_state(arg->res->parseState);
1954
1955 result.res = pushJsonbValue(&result.parseState,
1956 WJB_END_OBJECT, NULL);
1957
1958 out = JsonbValueToJsonb(result.res);
1959
1960 PG_RETURN_POINTER(out);
1961}
1962
1963
1964/*
1965 * Extract scalar value from raw-scalar pseudo-array jsonb.
1966 */
1967bool
1969{
1970 JsonbIterator *it;
1972 JsonbValue tmp;
1973
1975 {
1976 /* inform caller about actual type of container */
1977 res->type = (JsonContainerIsArray(jbc)) ? jbvArray : jbvObject;
1978 return false;
1979 }
1980
1981 /*
1982 * A root scalar is stored as an array of one element, so we get the array
1983 * and then its first (and only) member.
1984 */
1985 it = JsonbIteratorInit(jbc);
1986
1987 tok = JsonbIteratorNext(&it, &tmp, true);
1988 Assert(tok == WJB_BEGIN_ARRAY);
1989 Assert(tmp.val.array.nElems == 1 && tmp.val.array.rawScalar);
1990
1991 tok = JsonbIteratorNext(&it, res, true);
1992 Assert(tok == WJB_ELEM);
1994
1995 tok = JsonbIteratorNext(&it, &tmp, true);
1996 Assert(tok == WJB_END_ARRAY);
1997
1998 tok = JsonbIteratorNext(&it, &tmp, true);
1999 Assert(tok == WJB_DONE);
2000
2001 return true;
2002}
2003
2004/*
2005 * Emit correct, translatable cast error message
2006 */
2007static void
2008cannotCastJsonbValue(enum jbvType type, const char *sqltype)
2009{
2010 static const struct
2011 {
2012 enum jbvType type;
2013 const char *msg;
2014 }
2015 messages[] =
2016 {
2017 {jbvNull, gettext_noop("cannot cast jsonb null to type %s")},
2018 {jbvString, gettext_noop("cannot cast jsonb string to type %s")},
2019 {jbvNumeric, gettext_noop("cannot cast jsonb numeric to type %s")},
2020 {jbvBool, gettext_noop("cannot cast jsonb boolean to type %s")},
2021 {jbvArray, gettext_noop("cannot cast jsonb array to type %s")},
2022 {jbvObject, gettext_noop("cannot cast jsonb object to type %s")},
2023 {jbvBinary, gettext_noop("cannot cast jsonb array or object to type %s")}
2024 };
2025 int i;
2026
2027 for (i = 0; i < lengthof(messages); i++)
2028 if (messages[i].type == type)
2029 ereport(ERROR,
2030 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
2031 errmsg(messages[i].msg, sqltype)));
2032
2033 /* should be unreachable */
2034 elog(ERROR, "unknown jsonb type: %d", (int) type);
2035}
2036
2037Datum
2039{
2040 Jsonb *in = PG_GETARG_JSONB_P(0);
2041 JsonbValue v;
2042
2043 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvBool)
2044 cannotCastJsonbValue(v.type, "boolean");
2045
2046 PG_FREE_IF_COPY(in, 0);
2047
2048 PG_RETURN_BOOL(v.val.boolean);
2049}
2050
2051Datum
2053{
2054 Jsonb *in = PG_GETARG_JSONB_P(0);
2055 JsonbValue v;
2056 Numeric retValue;
2057
2058 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2059 cannotCastJsonbValue(v.type, "numeric");
2060
2061 /*
2062 * v.val.numeric points into jsonb body, so we need to make a copy to
2063 * return
2064 */
2065 retValue = DatumGetNumericCopy(NumericGetDatum(v.val.numeric));
2066
2067 PG_FREE_IF_COPY(in, 0);
2068
2069 PG_RETURN_NUMERIC(retValue);
2070}
2071
2072Datum
2074{
2075 Jsonb *in = PG_GETARG_JSONB_P(0);
2076 JsonbValue v;
2077 Datum retValue;
2078
2079 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2080 cannotCastJsonbValue(v.type, "smallint");
2081
2083 NumericGetDatum(v.val.numeric));
2084
2085 PG_FREE_IF_COPY(in, 0);
2086
2087 PG_RETURN_DATUM(retValue);
2088}
2089
2090Datum
2092{
2093 Jsonb *in = PG_GETARG_JSONB_P(0);
2094 JsonbValue v;
2095 Datum retValue;
2096
2097 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2098 cannotCastJsonbValue(v.type, "integer");
2099
2101 NumericGetDatum(v.val.numeric));
2102
2103 PG_FREE_IF_COPY(in, 0);
2104
2105 PG_RETURN_DATUM(retValue);
2106}
2107
2108Datum
2110{
2111 Jsonb *in = PG_GETARG_JSONB_P(0);
2112 JsonbValue v;
2113 Datum retValue;
2114
2115 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2116 cannotCastJsonbValue(v.type, "bigint");
2117
2119 NumericGetDatum(v.val.numeric));
2120
2121 PG_FREE_IF_COPY(in, 0);
2122
2123 PG_RETURN_DATUM(retValue);
2124}
2125
2126Datum
2128{
2129 Jsonb *in = PG_GETARG_JSONB_P(0);
2130 JsonbValue v;
2131 Datum retValue;
2132
2133 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2134 cannotCastJsonbValue(v.type, "real");
2135
2137 NumericGetDatum(v.val.numeric));
2138
2139 PG_FREE_IF_COPY(in, 0);
2140
2141 PG_RETURN_DATUM(retValue);
2142}
2143
2144Datum
2146{
2147 Jsonb *in = PG_GETARG_JSONB_P(0);
2148 JsonbValue v;
2149 Datum retValue;
2150
2151 if (!JsonbExtractScalar(&in->root, &v) || v.type != jbvNumeric)
2152 cannotCastJsonbValue(v.type, "double precision");
2153
2155 NumericGetDatum(v.val.numeric));
2156
2157 PG_FREE_IF_COPY(in, 0);
2158
2159 PG_RETURN_DATUM(retValue);
2160}
2161
2162/*
2163 * Convert jsonb to a C-string stripping quotes from scalar strings.
2164 */
2165char *
2167{
2168 if (JB_ROOT_IS_SCALAR(jb))
2169 {
2170 JsonbValue v;
2171
2172 (void) JsonbExtractScalar(&jb->root, &v);
2173
2174 if (v.type == jbvString)
2175 return pnstrdup(v.val.string.val, v.val.string.len);
2176 else if (v.type == jbvBool)
2177 return pstrdup(v.val.boolean ? "true" : "false");
2178 else if (v.type == jbvNumeric)
2180 PointerGetDatum(v.val.numeric)));
2181 else if (v.type == jbvNull)
2182 return pstrdup("null");
2183 else
2184 {
2185 elog(ERROR, "unrecognized jsonb value type %d", v.type);
2186 return NULL;
2187 }
2188 }
2189 else
2190 return JsonbToCString(NULL, &jb->root, VARSIZE(jb));
2191}
#define ARR_NDIM(a)
Definition: array.h:290
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:263
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
#define ARR_DIMS(a)
Definition: array.h:294
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3631
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3697
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:57
Datum numeric_int8(PG_FUNCTION_ARGS)
Definition: numeric.c:4653
Datum numeric_uplus(PG_FUNCTION_ARGS)
Definition: numeric.c:1462
Datum numeric_int4(PG_FUNCTION_ARGS)
Definition: numeric.c:4565
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:816
Datum numeric_int2(PG_FUNCTION_ARGS)
Definition: numeric.c:4671
Datum numeric_float8(PG_FUNCTION_ARGS)
Definition: numeric.c:4746
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:637
Datum numeric_float4(PG_FUNCTION_ARGS)
Definition: numeric.c:4840
#define TextDatumGetCString(d)
Definition: builtins.h:98
#define NameStr(name)
Definition: c.h:700
#define gettext_noop(x)
Definition: c.h:1150
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:201
#define Assert(condition)
Definition: c.h:812
int16_t int16
Definition: c.h:480
int32_t int32
Definition: c.h:481
#define lengthof(array)
Definition: c.h:742
struct typedefs * types
Definition: ecpg.c:30
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1910
bool DirectInputFunctionCallSafe(PGFunction func, char *str, Oid typioparam, int32 typmod, fmNodePtr escontext, Datum *result)
Definition: fmgr.c:1640
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:679
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
#define DatumGetTextPP(X)
Definition: fmgr.h:292
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_NULL()
Definition: fmgr.h:345
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:645
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
int extract_variadic_args(FunctionCallInfo fcinfo, int variadic_start, bool convert_unknown, Datum **args, Oid **types, bool **nulls)
Definition: funcapi.c:2005
const char * str
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:466
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:456
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:450
#define nitems(x)
Definition: indent.h:31
#define token
Definition: indent_globs.h:126
long val
Definition: informix.c:689
int i
Definition: isn.c:72
char * JsonEncodeDateTime(char *buf, Datum value, Oid typid, const int *tzp)
Definition: json.c:310
void escape_json_with_len(StringInfo buf, const char *str, int len)
Definition: json.c:1631
JsonLexContext * makeJsonLexContextCstringLen(JsonLexContext *lex, const char *json, size_t len, int encoding, bool need_escapes)
Definition: jsonapi.c:392
void freeJsonLexContext(JsonLexContext *lex)
Definition: jsonapi.c:687
JsonParseErrorType
Definition: jsonapi.h:35
@ JSON_SEM_ACTION_FAILED
Definition: jsonapi.h:59
@ JSON_SUCCESS
Definition: jsonapi.h:36
JsonTokenType
Definition: jsonapi.h:18
@ JSON_TOKEN_FALSE
Definition: jsonapi.h:29
@ JSON_TOKEN_TRUE
Definition: jsonapi.h:28
@ JSON_TOKEN_NULL
Definition: jsonapi.h:30
@ JSON_TOKEN_NUMBER
Definition: jsonapi.h:21
@ JSON_TOKEN_STRING
Definition: jsonapi.h:20
Datum jsonb_from_text(text *js, bool unique_keys)
Definition: jsonb.c:147
static Datum jsonb_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
Definition: jsonb.c:1501
static JsonParseErrorType jsonb_in_object_start(void *pstate)
Definition: jsonb.c:290
Datum jsonb_int4(PG_FUNCTION_ARGS)
Definition: jsonb.c:2091
Datum jsonb_recv(PG_FUNCTION_ARGS)
Definition: jsonb.c:89
Datum jsonb_object_agg_strict_transfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1906
Datum to_jsonb(PG_FUNCTION_ARGS)
Definition: jsonb.c:1088
char * JsonbUnquote(Jsonb *jb)
Definition: jsonb.c:2166
Datum jsonb_build_array_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null)
Definition: jsonb.c:1210
static Datum jsonb_from_cstring(char *json, int len, bool unique_keys, Node *escontext)
Definition: jsonb.c:248
static void datum_to_jsonb_internal(Datum val, bool is_null, JsonbInState *result, JsonTypeCategory tcategory, Oid outfuncoid, bool key_scalar)
Definition: jsonb.c:638
Datum jsonb_build_array_noargs(PG_FUNCTION_ARGS)
Definition: jsonb.c:1258
Datum jsonb_object_agg_unique_strict_transfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1924
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition: jsonb.c:73
Datum jsonb_build_object_noargs(PG_FUNCTION_ARGS)
Definition: jsonb.c:1197
Datum jsonb_agg_transfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1625
Datum jsonb_object_two_arg(PG_FUNCTION_ARGS)
Definition: jsonb.c:1379
static const char * JsonbContainerTypeName(JsonbContainer *jbc)
Definition: jsonb.c:159
Datum jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1896
static JsonParseErrorType jsonb_in_array_end(void *pstate)
Definition: jsonb.c:321
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:491
Datum jsonb_build_array(PG_FUNCTION_ARGS)
Definition: jsonb.c:1237
Datum jsonb_int8(PG_FUNCTION_ARGS)
Definition: jsonb.c:2109
static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
Definition: jsonb.c:349
static void cannotCastJsonbValue(enum jbvType type, const char *sqltype)
Definition: jsonb.c:2008
static void add_jsonb(Datum val, bool is_null, JsonbInState *result, Oid val_type, bool key_scalar)
Definition: jsonb.c:1016
static JsonbParseState * clone_parse_state(JsonbParseState *state)
Definition: jsonb.c:1471
static JsonParseErrorType jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
Definition: jsonb.c:331
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:473
Datum jsonb_object_agg_unique_transfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1915
Datum jsonb_out(PG_FUNCTION_ARGS)
Definition: jsonb.c:108
Datum jsonb_numeric(PG_FUNCTION_ARGS)
Definition: jsonb.c:2052
static void array_to_jsonb_internal(Datum array, JsonbInState *result)
Definition: jsonb.c:894
const char * JsonbTypeName(JsonbValue *val)
Definition: jsonb.c:180
struct JsonbAggState JsonbAggState
Datum jsonb_object(PG_FUNCTION_ARGS)
Definition: jsonb.c:1279
Datum jsonb_build_object_worker(int nargs, const Datum *args, const bool *nulls, const Oid *types, bool absent_on_null, bool unique_keys)
Definition: jsonb.c:1125
struct JsonbInState JsonbInState
Datum jsonb_int2(PG_FUNCTION_ARGS)
Definition: jsonb.c:2073
static void composite_to_jsonb(Datum composite, JsonbInState *result)
Definition: jsonb.c:942
Datum jsonb_float4(PG_FUNCTION_ARGS)
Definition: jsonb.c:2127
Datum jsonb_agg_strict_transfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1634
static void add_indent(StringInfo out, bool indent, int level)
Definition: jsonb.c:615
Datum jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1930
static JsonParseErrorType jsonb_in_array_start(void *pstate)
Definition: jsonb.c:311
bool JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
Definition: jsonb.c:1968
Datum datum_to_jsonb(Datum val, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: jsonb.c:1112
Datum jsonb_build_object(PG_FUNCTION_ARGS)
Definition: jsonb.c:1177
static Datum jsonb_object_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null, bool unique_keys)
Definition: jsonb.c:1673
Datum jsonb_typeof(PG_FUNCTION_ARGS)
Definition: jsonb.c:229
Datum jsonb_bool(PG_FUNCTION_ARGS)
Definition: jsonb.c:2038
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:482
static JsonParseErrorType jsonb_in_object_end(void *pstate)
Definition: jsonb.c:301
static JsonParseErrorType jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
Definition: jsonb.c:379
Datum jsonb_agg_finalfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1640
Datum jsonb_float8(PG_FUNCTION_ARGS)
Definition: jsonb.c:2145
bool to_jsonb_is_immutable(Oid typoid)
Definition: jsonb.c:1049
static bool checkStringLen(size_t len, Node *escontext)
Definition: jsonb.c:277
Datum jsonb_send(PG_FUNCTION_ARGS)
Definition: jsonb.c:124
static void array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, const Datum *vals, const bool *nulls, int *valcount, JsonTypeCategory tcategory, Oid outfuncoid)
Definition: jsonb.c:862
jbvType
Definition: jsonb.h:226
@ jbvObject
Definition: jsonb.h:234
@ jbvNumeric
Definition: jsonb.h:230
@ jbvBool
Definition: jsonb.h:231
@ jbvArray
Definition: jsonb.h:233
@ jbvBinary
Definition: jsonb.h:236
@ jbvNull
Definition: jsonb.h:228
@ jbvDatetime
Definition: jsonb.h:244
@ jbvString
Definition: jsonb.h:229
#define JsonContainerIsScalar(jc)
Definition: jsonb.h:207
#define JsonContainerIsArray(jc)
Definition: jsonb.h:209
static Datum JsonbPGetDatum(const Jsonb *p)
Definition: jsonb.h:386
#define IsAJsonbScalar(jsonbval)
Definition: jsonb.h:297
#define JENTRY_OFFLENMASK
Definition: jsonb.h:138
#define PG_GETARG_JSONB_P(x)
Definition: jsonb.h:391
#define JsonContainerIsObject(jc)
Definition: jsonb.h:208
static Jsonb * DatumGetJsonbP(Datum d)
Definition: jsonb.h:374
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:220
JsonbIteratorToken
Definition: jsonb.h:21
@ WJB_KEY
Definition: jsonb.h:23
@ WJB_DONE
Definition: jsonb.h:22
@ WJB_END_ARRAY
Definition: jsonb.h:27
@ WJB_VALUE
Definition: jsonb.h:24
@ WJB_END_OBJECT
Definition: jsonb.h:29
@ WJB_ELEM
Definition: jsonb.h:25
@ WJB_BEGIN_OBJECT
Definition: jsonb.h:28
@ WJB_BEGIN_ARRAY
Definition: jsonb.h:26
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:573
JsonbIterator * JsonbIteratorInit(JsonbContainer *container)
Definition: jsonb_util.c:824
JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
Definition: jsonb_util.c:860
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:92
JsonLexContext * makeJsonLexContext(JsonLexContext *lex, text *json, bool need_escapes)
Definition: jsonfuncs.c:539
void json_categorize_type(Oid typoid, bool is_jsonb, JsonTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonfuncs.c:5976
bool pg_parse_json_or_errsave(JsonLexContext *lex, const JsonSemAction *sem, Node *escontext)
Definition: jsonfuncs.c:518
#define pg_parse_json_or_ereport(lex, sem)
Definition: jsonfuncs.h:47
JsonTypeCategory
Definition: jsonfuncs.h:69
@ JSONTYPE_JSON
Definition: jsonfuncs.h:76
@ JSONTYPE_NULL
Definition: jsonfuncs.h:70
@ JSONTYPE_TIMESTAMP
Definition: jsonfuncs.h:74
@ JSONTYPE_NUMERIC
Definition: jsonfuncs.h:72
@ JSONTYPE_DATE
Definition: jsonfuncs.h:73
@ JSONTYPE_BOOL
Definition: jsonfuncs.h:71
@ JSONTYPE_OTHER
Definition: jsonfuncs.h:81
@ JSONTYPE_CAST
Definition: jsonfuncs.h:80
@ JSONTYPE_COMPOSITE
Definition: jsonfuncs.h:79
@ JSONTYPE_ARRAY
Definition: jsonfuncs.h:78
@ JSONTYPE_TIMESTAMPTZ
Definition: jsonfuncs.h:75
@ JSONTYPE_JSONB
Definition: jsonfuncs.h:77
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2271
char func_volatile(Oid funcid)
Definition: lsyscache.c:1780
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1707
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4504
static Numeric DatumGetNumericCopy(Datum X)
Definition: numeric.h:67
static Numeric DatumGetNumeric(Datum X)
Definition: numeric.h:61
#define PG_RETURN_NUMERIC(x)
Definition: numeric.h:80
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
NameData attname
Definition: pg_attribute.h:41
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:200
void * arg
static const struct exclude_list_item skip[]
Definition: pg_checksums.c:107
const void size_t len
static char * buf
Definition: pg_test_fsync.c:72
char typalign
Definition: pg_type.h:176
#define snprintf
Definition: port.h:238
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:350
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:172
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:546
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint8(StringInfo buf, uint8 i)
Definition: pqformat.h:128
void check_stack_depth(void)
Definition: stack_depth.c:95
void destroyStringInfo(StringInfo str)
Definition: stringinfo.c:409
StringInfo makeStringInfo(void)
Definition: stringinfo.c:72
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:337
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:260
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
StringInfoData * StringInfo
Definition: stringinfo.h:54
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:231
FmgrInfo * flinfo
Definition: fmgr.h:87
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
json_struct_action array_end
Definition: jsonapi.h:151
json_struct_action object_start
Definition: jsonapi.h:148
json_ofield_action object_field_start
Definition: jsonapi.h:152
json_scalar_action scalar
Definition: jsonapi.h:156
void * semstate
Definition: jsonapi.h:147
json_struct_action array_start
Definition: jsonapi.h:150
json_struct_action object_end
Definition: jsonapi.h:149
JsonTypeCategory val_category
Definition: jsonb.c:41
JsonTypeCategory key_category
Definition: jsonb.c:39
Oid key_output_func
Definition: jsonb.c:40
JsonbInState * res
Definition: jsonb.c:38
Oid val_output_func
Definition: jsonb.c:42
uint32 header
Definition: jsonb.h:192
JsonbParseState * parseState
Definition: jsonb.c:30
Node * escontext
Definition: jsonb.c:33
bool unique_keys
Definition: jsonb.c:32
JsonbValue * res
Definition: jsonb.c:31
bool unique_keys
Definition: jsonb.h:324
struct JsonbParseState * next
Definition: jsonb.h:323
bool skip_nulls
Definition: jsonb.h:325
JsonbValue contVal
Definition: jsonb.h:321
enum jbvType type
Definition: jsonb.h:255
char * val
Definition: jsonb.h:264
Definition: jsonb.h:213
JsonbContainer root
Definition: jsonb.h:215
Definition: nodes.h:129
Definition: regguts.h:323
Definition: c.h:641
static JsonSemAction sem
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:212
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:153
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1920
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE(PTR)
Definition: varatt.h:279
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
text * cstring_to_text(const char *s)
Definition: varlena.c:184
const char * type