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