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