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