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