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