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