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