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