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