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-2017, 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 
347  switch (tokentype)
348  {
349 
350  case JSON_TOKEN_STRING:
351  Assert(token != NULL);
352  v.type = jbvString;
353  v.val.string.len = checkStringLen(strlen(token));
354  v.val.string.val = token;
355  break;
356  case JSON_TOKEN_NUMBER:
357 
358  /*
359  * No need to check size of numeric values, because maximum
360  * numeric size is well below the JsonbValue restriction
361  */
362  Assert(token != NULL);
363  v.type = jbvNumeric;
365 
366  break;
367  case JSON_TOKEN_TRUE:
368  v.type = jbvBool;
369  v.val.boolean = true;
370 
371  break;
372  case JSON_TOKEN_FALSE:
373  v.type = jbvBool;
374  v.val.boolean = false;
375 
376  break;
377  case JSON_TOKEN_NULL:
378  v.type = jbvNull;
379  break;
380  default:
381  /* should not be possible */
382  elog(ERROR, "invalid json token type");
383  break;
384  }
385 
386  if (_state->parseState == NULL)
387  {
388  /* single scalar */
389  JsonbValue va;
390 
391  va.type = jbvArray;
392  va.val.array.rawScalar = true;
393  va.val.array.nElems = 1;
394 
395  _state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_ARRAY, &va);
396  _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
397  _state->res = pushJsonbValue(&_state->parseState, WJB_END_ARRAY, NULL);
398  }
399  else
400  {
401  JsonbValue *o = &_state->parseState->contVal;
402 
403  switch (o->type)
404  {
405  case jbvArray:
406  _state->res = pushJsonbValue(&_state->parseState, WJB_ELEM, &v);
407  break;
408  case jbvObject:
409  _state->res = pushJsonbValue(&_state->parseState, WJB_VALUE, &v);
410  break;
411  default:
412  elog(ERROR, "unexpected parent of nested structure");
413  }
414  }
415 }
416 
417 /*
418  * JsonbToCString
419  * Converts jsonb value to a C-string.
420  *
421  * If 'out' argument is non-null, the resulting C-string is stored inside the
422  * StringBuffer. The resulting string is always returned.
423  *
424  * A typical case for passing the StringInfo in rather than NULL is where the
425  * caller wants access to the len attribute without having to call strlen, e.g.
426  * if they are converting it to a text* object.
427  */
428 char *
429 JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
430 {
431  return JsonbToCStringWorker(out, in, estimated_len, false);
432 }
433 
434 /*
435  * same thing but with indentation turned on
436  */
437 char *
438 JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
439 {
440  return JsonbToCStringWorker(out, in, estimated_len, true);
441 }
442 
443 /*
444  * common worker for above two functions
445  */
446 static char *
447 JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
448 {
449  bool first = true;
450  JsonbIterator *it;
451  JsonbValue v;
453  int level = 0;
454  bool redo_switch = false;
455 
456  /* If we are indenting, don't add a space after a comma */
457  int ispaces = indent ? 1 : 2;
458 
459  /*
460  * Don't indent the very first item. This gets set to the indent flag at
461  * the bottom of the loop.
462  */
463  bool use_indent = false;
464  bool raw_scalar = false;
465  bool last_was_key = false;
466 
467  if (out == NULL)
468  out = makeStringInfo();
469 
470  enlargeStringInfo(out, (estimated_len >= 0) ? estimated_len : 64);
471 
472  it = JsonbIteratorInit(in);
473 
474  while (redo_switch ||
475  ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE))
476  {
477  redo_switch = false;
478  switch (type)
479  {
480  case WJB_BEGIN_ARRAY:
481  if (!first)
482  appendBinaryStringInfo(out, ", ", ispaces);
483 
484  if (!v.val.array.rawScalar)
485  {
486  add_indent(out, use_indent && !last_was_key, level);
487  appendStringInfoCharMacro(out, '[');
488  }
489  else
490  raw_scalar = true;
491 
492  first = true;
493  level++;
494  break;
495  case WJB_BEGIN_OBJECT:
496  if (!first)
497  appendBinaryStringInfo(out, ", ", ispaces);
498 
499  add_indent(out, use_indent && !last_was_key, level);
500  appendStringInfoCharMacro(out, '{');
501 
502  first = true;
503  level++;
504  break;
505  case WJB_KEY:
506  if (!first)
507  appendBinaryStringInfo(out, ", ", ispaces);
508  first = true;
509 
510  add_indent(out, use_indent, level);
511 
512  /* json rules guarantee this is a string */
513  jsonb_put_escaped_value(out, &v);
514  appendBinaryStringInfo(out, ": ", 2);
515 
516  type = JsonbIteratorNext(&it, &v, false);
517  if (type == WJB_VALUE)
518  {
519  first = false;
520  jsonb_put_escaped_value(out, &v);
521  }
522  else
523  {
524  Assert(type == WJB_BEGIN_OBJECT || type == WJB_BEGIN_ARRAY);
525 
526  /*
527  * We need to rerun the current switch() since we need to
528  * output the object which we just got from the iterator
529  * before calling the iterator again.
530  */
531  redo_switch = true;
532  }
533  break;
534  case WJB_ELEM:
535  if (!first)
536  appendBinaryStringInfo(out, ", ", ispaces);
537  first = false;
538 
539  if (!raw_scalar)
540  add_indent(out, use_indent, level);
541  jsonb_put_escaped_value(out, &v);
542  break;
543  case WJB_END_ARRAY:
544  level--;
545  if (!raw_scalar)
546  {
547  add_indent(out, use_indent, level);
548  appendStringInfoCharMacro(out, ']');
549  }
550  first = false;
551  break;
552  case WJB_END_OBJECT:
553  level--;
554  add_indent(out, use_indent, level);
555  appendStringInfoCharMacro(out, '}');
556  first = false;
557  break;
558  default:
559  elog(ERROR, "unknown jsonb iterator token type");
560  }
561  use_indent = indent;
562  last_was_key = redo_switch;
563  }
564 
565  Assert(level == 0);
566 
567  return out->data;
568 }
569 
570 static void
571 add_indent(StringInfo out, bool indent, int level)
572 {
573  if (indent)
574  {
575  int i;
576 
577  appendStringInfoCharMacro(out, '\n');
578  for (i = 0; i < level; i++)
579  appendBinaryStringInfo(out, " ", 4);
580  }
581 }
582 
583 
584 /*
585  * Determine how we want to render values of a given type in datum_to_jsonb.
586  *
587  * Given the datatype OID, return its JsonbTypeCategory, as well as the type's
588  * output function OID. If the returned category is JSONBTYPE_JSONCAST,
589  * we return the OID of the relevant cast function instead.
590  */
591 static void
593  JsonbTypeCategory *tcategory,
594  Oid *outfuncoid)
595 {
596  bool typisvarlena;
597 
598  /* Look through any domain */
599  typoid = getBaseType(typoid);
600 
601  *outfuncoid = InvalidOid;
602 
603  /*
604  * We need to get the output function for everything except date and
605  * timestamp types, booleans, array and composite types, json and jsonb,
606  * and non-builtin types where there's a cast to json. In this last case
607  * we return the oid of the cast function instead.
608  */
609 
610  switch (typoid)
611  {
612  case BOOLOID:
613  *tcategory = JSONBTYPE_BOOL;
614  break;
615 
616  case INT2OID:
617  case INT4OID:
618  case INT8OID:
619  case FLOAT4OID:
620  case FLOAT8OID:
621  case NUMERICOID:
622  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
623  *tcategory = JSONBTYPE_NUMERIC;
624  break;
625 
626  case DATEOID:
627  *tcategory = JSONBTYPE_DATE;
628  break;
629 
630  case TIMESTAMPOID:
631  *tcategory = JSONBTYPE_TIMESTAMP;
632  break;
633 
634  case TIMESTAMPTZOID:
635  *tcategory = JSONBTYPE_TIMESTAMPTZ;
636  break;
637 
638  case JSONBOID:
639  *tcategory = JSONBTYPE_JSONB;
640  break;
641 
642  case JSONOID:
643  *tcategory = JSONBTYPE_JSON;
644  break;
645 
646  default:
647  /* Check for arrays and composites */
648  if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
649  || typoid == RECORDARRAYOID)
650  *tcategory = JSONBTYPE_ARRAY;
651  else if (type_is_rowtype(typoid)) /* includes RECORDOID */
652  *tcategory = JSONBTYPE_COMPOSITE;
653  else
654  {
655  /* It's probably the general case ... */
656  *tcategory = JSONBTYPE_OTHER;
657 
658  /*
659  * but first let's look for a cast to json (note: not to
660  * jsonb) if it's not built-in.
661  */
662  if (typoid >= FirstNormalObjectId)
663  {
664  Oid castfunc;
665  CoercionPathType ctype;
666 
667  ctype = find_coercion_pathway(JSONOID, typoid,
668  COERCION_EXPLICIT, &castfunc);
669  if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
670  {
671  *tcategory = JSONBTYPE_JSONCAST;
672  *outfuncoid = castfunc;
673  }
674  else
675  {
676  /* not a cast type, so just get the usual output func */
677  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
678  }
679  }
680  else
681  {
682  /* any other builtin type */
683  getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
684  }
685  break;
686  }
687  }
688 }
689 
690 /*
691  * Turn a Datum into jsonb, adding it to the result JsonbInState.
692  *
693  * tcategory and outfuncoid are from a previous call to json_categorize_type,
694  * except that if is_null is true then they can be invalid.
695  *
696  * If key_scalar is true, the value is stored as a key, so insist
697  * it's of an acceptable type, and force it to be a jbvString.
698  */
699 static void
700 datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
701  JsonbTypeCategory tcategory, Oid outfuncoid,
702  bool key_scalar)
703 {
704  char *outputstr;
705  bool numeric_error;
706  JsonbValue jb;
707  bool scalar_jsonb = false;
708 
710 
711  /* Convert val to a JsonbValue in jb (in most cases) */
712  if (is_null)
713  {
714  Assert(!key_scalar);
715  jb.type = jbvNull;
716  }
717  else if (key_scalar &&
718  (tcategory == JSONBTYPE_ARRAY ||
719  tcategory == JSONBTYPE_COMPOSITE ||
720  tcategory == JSONBTYPE_JSON ||
721  tcategory == JSONBTYPE_JSONB ||
722  tcategory == JSONBTYPE_JSONCAST))
723  {
724  ereport(ERROR,
725  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
726  errmsg("key value must be scalar, not array, composite, or json")));
727  }
728  else
729  {
730  if (tcategory == JSONBTYPE_JSONCAST)
731  val = OidFunctionCall1(outfuncoid, val);
732 
733  switch (tcategory)
734  {
735  case JSONBTYPE_ARRAY:
736  array_to_jsonb_internal(val, result);
737  break;
738  case JSONBTYPE_COMPOSITE:
739  composite_to_jsonb(val, result);
740  break;
741  case JSONBTYPE_BOOL:
742  if (key_scalar)
743  {
744  outputstr = DatumGetBool(val) ? "true" : "false";
745  jb.type = jbvString;
746  jb.val.string.len = strlen(outputstr);
747  jb.val.string.val = outputstr;
748  }
749  else
750  {
751  jb.type = jbvBool;
752  jb.val.boolean = DatumGetBool(val);
753  }
754  break;
755  case JSONBTYPE_NUMERIC:
756  outputstr = OidOutputFunctionCall(outfuncoid, val);
757  if (key_scalar)
758  {
759  /* always quote keys */
760  jb.type = jbvString;
761  jb.val.string.len = strlen(outputstr);
762  jb.val.string.val = outputstr;
763  }
764  else
765  {
766  /*
767  * Make it numeric if it's a valid JSON number, otherwise
768  * a string. Invalid numeric output will always have an
769  * 'N' or 'n' in it (I think).
770  */
771  numeric_error = (strchr(outputstr, 'N') != NULL ||
772  strchr(outputstr, 'n') != NULL);
773  if (!numeric_error)
774  {
775  jb.type = jbvNumeric;
776  jb.val.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(outputstr), 0, -1));
777 
778  pfree(outputstr);
779  }
780  else
781  {
782  jb.type = jbvString;
783  jb.val.string.len = strlen(outputstr);
784  jb.val.string.val = outputstr;
785  }
786  }
787  break;
788  case JSONBTYPE_DATE:
789  {
790  DateADT date;
791  struct pg_tm tm;
792  char buf[MAXDATELEN + 1];
793 
794  date = DatumGetDateADT(val);
795  /* Same as date_out(), but forcing DateStyle */
796  if (DATE_NOT_FINITE(date))
797  EncodeSpecialDate(date, buf);
798  else
799  {
801  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
802  EncodeDateOnly(&tm, USE_XSD_DATES, buf);
803  }
804  jb.type = jbvString;
805  jb.val.string.len = strlen(buf);
806  jb.val.string.val = pstrdup(buf);
807  }
808  break;
809  case JSONBTYPE_TIMESTAMP:
810  {
812  struct pg_tm tm;
813  fsec_t fsec;
814  char buf[MAXDATELEN + 1];
815 
816  timestamp = DatumGetTimestamp(val);
817  /* Same as timestamp_out(), but forcing DateStyle */
818  if (TIMESTAMP_NOT_FINITE(timestamp))
819  EncodeSpecialTimestamp(timestamp, buf);
820  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
821  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
822  else
823  ereport(ERROR,
824  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
825  errmsg("timestamp out of range")));
826  jb.type = jbvString;
827  jb.val.string.len = strlen(buf);
828  jb.val.string.val = pstrdup(buf);
829  }
830  break;
832  {
834  struct pg_tm tm;
835  int tz;
836  fsec_t fsec;
837  const char *tzn = NULL;
838  char buf[MAXDATELEN + 1];
839 
840  timestamp = DatumGetTimestampTz(val);
841  /* Same as timestamptz_out(), but forcing DateStyle */
842  if (TIMESTAMP_NOT_FINITE(timestamp))
843  EncodeSpecialTimestamp(timestamp, buf);
844  else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
845  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
846  else
847  ereport(ERROR,
848  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
849  errmsg("timestamp out of range")));
850  jb.type = jbvString;
851  jb.val.string.len = strlen(buf);
852  jb.val.string.val = pstrdup(buf);
853  }
854  break;
855  case JSONBTYPE_JSONCAST:
856  case JSONBTYPE_JSON:
857  {
858  /* parse the json right into the existing result object */
859  JsonLexContext *lex;
860  JsonSemAction sem;
861  text *json = DatumGetTextPP(val);
862 
863  lex = makeJsonLexContext(json, true);
864 
865  memset(&sem, 0, sizeof(sem));
866 
867  sem.semstate = (void *) result;
868 
873  sem.scalar = jsonb_in_scalar;
875 
876  pg_parse_json(lex, &sem);
877 
878  }
879  break;
880  case JSONBTYPE_JSONB:
881  {
882  Jsonb *jsonb = DatumGetJsonbP(val);
883  JsonbIterator *it;
884 
885  it = JsonbIteratorInit(&jsonb->root);
886 
887  if (JB_ROOT_IS_SCALAR(jsonb))
888  {
889  (void) JsonbIteratorNext(&it, &jb, true);
890  Assert(jb.type == jbvArray);
891  (void) JsonbIteratorNext(&it, &jb, true);
892  scalar_jsonb = true;
893  }
894  else
895  {
897 
898  while ((type = JsonbIteratorNext(&it, &jb, false))
899  != WJB_DONE)
900  {
901  if (type == WJB_END_ARRAY || type == WJB_END_OBJECT ||
902  type == WJB_BEGIN_ARRAY || type == WJB_BEGIN_OBJECT)
903  result->res = pushJsonbValue(&result->parseState,
904  type, NULL);
905  else
906  result->res = pushJsonbValue(&result->parseState,
907  type, &jb);
908  }
909  }
910  }
911  break;
912  default:
913  outputstr = OidOutputFunctionCall(outfuncoid, val);
914  jb.type = jbvString;
915  jb.val.string.len = checkStringLen(strlen(outputstr));
916  jb.val.string.val = outputstr;
917  break;
918  }
919  }
920 
921  /* Now insert jb into result, unless we did it recursively */
922  if (!is_null && !scalar_jsonb &&
923  tcategory >= JSONBTYPE_JSON && tcategory <= JSONBTYPE_JSONCAST)
924  {
925  /* work has been done recursively */
926  return;
927  }
928  else if (result->parseState == NULL)
929  {
930  /* single root scalar */
931  JsonbValue va;
932 
933  va.type = jbvArray;
934  va.val.array.rawScalar = true;
935  va.val.array.nElems = 1;
936 
937  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, &va);
938  result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
939  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
940  }
941  else
942  {
943  JsonbValue *o = &result->parseState->contVal;
944 
945  switch (o->type)
946  {
947  case jbvArray:
948  result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
949  break;
950  case jbvObject:
951  result->res = pushJsonbValue(&result->parseState,
952  key_scalar ? WJB_KEY : WJB_VALUE,
953  &jb);
954  break;
955  default:
956  elog(ERROR, "unexpected parent of nested structure");
957  }
958  }
959 }
960 
961 /*
962  * Process a single dimension of an array.
963  * If it's the innermost dimension, output the values, otherwise call
964  * ourselves recursively to process the next dimension.
965  */
966 static void
967 array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *vals,
968  bool *nulls, int *valcount, JsonbTypeCategory tcategory,
969  Oid outfuncoid)
970 {
971  int i;
972 
973  Assert(dim < ndims);
974 
975  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
976 
977  for (i = 1; i <= dims[dim]; i++)
978  {
979  if (dim + 1 == ndims)
980  {
981  datum_to_jsonb(vals[*valcount], nulls[*valcount], result, tcategory,
982  outfuncoid, false);
983  (*valcount)++;
984  }
985  else
986  {
987  array_dim_to_jsonb(result, dim + 1, ndims, dims, vals, nulls,
988  valcount, tcategory, outfuncoid);
989  }
990  }
991 
992  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
993 }
994 
995 /*
996  * Turn an array into JSON.
997  */
998 static void
1000 {
1001  ArrayType *v = DatumGetArrayTypeP(array);
1002  Oid element_type = ARR_ELEMTYPE(v);
1003  int *dim;
1004  int ndim;
1005  int nitems;
1006  int count = 0;
1007  Datum *elements;
1008  bool *nulls;
1009  int16 typlen;
1010  bool typbyval;
1011  char typalign;
1012  JsonbTypeCategory tcategory;
1013  Oid outfuncoid;
1014 
1015  ndim = ARR_NDIM(v);
1016  dim = ARR_DIMS(v);
1017  nitems = ArrayGetNItems(ndim, dim);
1018 
1019  if (nitems <= 0)
1020  {
1021  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
1022  result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
1023  return;
1024  }
1025 
1026  get_typlenbyvalalign(element_type,
1027  &typlen, &typbyval, &typalign);
1028 
1029  jsonb_categorize_type(element_type,
1030  &tcategory, &outfuncoid);
1031 
1032  deconstruct_array(v, element_type, typlen, typbyval,
1033  typalign, &elements, &nulls,
1034  &nitems);
1035 
1036  array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory,
1037  outfuncoid);
1038 
1039  pfree(elements);
1040  pfree(nulls);
1041 }
1042 
1043 /*
1044  * Turn a composite / record into JSON.
1045  */
1046 static void
1048 {
1049  HeapTupleHeader td;
1050  Oid tupType;
1051  int32 tupTypmod;
1052  TupleDesc tupdesc;
1053  HeapTupleData tmptup,
1054  *tuple;
1055  int i;
1056 
1057  td = DatumGetHeapTupleHeader(composite);
1058 
1059  /* Extract rowtype info and find a tupdesc */
1060  tupType = HeapTupleHeaderGetTypeId(td);
1061  tupTypmod = HeapTupleHeaderGetTypMod(td);
1062  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1063 
1064  /* Build a temporary HeapTuple control structure */
1065  tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
1066  tmptup.t_data = td;
1067  tuple = &tmptup;
1068 
1069  result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_OBJECT, NULL);
1070 
1071  for (i = 0; i < tupdesc->natts; i++)
1072  {
1073  Datum val;
1074  bool isnull;
1075  char *attname;
1076  JsonbTypeCategory tcategory;
1077  Oid outfuncoid;
1078  JsonbValue v;
1079  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1080 
1081  if (att->attisdropped)
1082  continue;
1083 
1084  attname = NameStr(att->attname);
1085 
1086  v.type = jbvString;
1087  /* don't need checkStringLen here - can't exceed maximum name length */
1088  v.val.string.len = strlen(attname);
1089  v.val.string.val = attname;
1090 
1091  result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
1092 
1093  val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
1094 
1095  if (isnull)
1096  {
1097  tcategory = JSONBTYPE_NULL;
1098  outfuncoid = InvalidOid;
1099  }
1100  else
1101  jsonb_categorize_type(att->atttypid, &tcategory, &outfuncoid);
1102 
1103  datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false);
1104  }
1105 
1106  result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
1107  ReleaseTupleDesc(tupdesc);
1108 }
1109 
1110 /*
1111  * Append JSON text for "val" to "result".
1112  *
1113  * This is just a thin wrapper around datum_to_jsonb. If the same type will be
1114  * printed many times, avoid using this; better to do the jsonb_categorize_type
1115  * lookups only once.
1116  */
1117 
1118 static void
1119 add_jsonb(Datum val, bool is_null, JsonbInState *result,
1120  Oid val_type, bool key_scalar)
1121 {
1122  JsonbTypeCategory tcategory;
1123  Oid outfuncoid;
1124 
1125  if (val_type == InvalidOid)
1126  ereport(ERROR,
1127  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1128  errmsg("could not determine input data type")));
1129 
1130  if (is_null)
1131  {
1132  tcategory = JSONBTYPE_NULL;
1133  outfuncoid = InvalidOid;
1134  }
1135  else
1136  jsonb_categorize_type(val_type,
1137  &tcategory, &outfuncoid);
1138 
1139  datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
1140 }
1141 
1142 /*
1143  * SQL function to_jsonb(anyvalue)
1144  */
1145 Datum
1147 {
1148  Datum val = PG_GETARG_DATUM(0);
1149  Oid val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
1150  JsonbInState result;
1151  JsonbTypeCategory tcategory;
1152  Oid outfuncoid;
1153 
1154  if (val_type == InvalidOid)
1155  ereport(ERROR,
1156  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1157  errmsg("could not determine input data type")));
1158 
1159  jsonb_categorize_type(val_type,
1160  &tcategory, &outfuncoid);
1161 
1162  memset(&result, 0, sizeof(JsonbInState));
1163 
1164  datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
1165 
1167 }
1168 
1169 /*
1170  * SQL function jsonb_build_object(variadic "any")
1171  */
1172 Datum
1174 {
1175  int nargs;
1176  int i;
1177  JsonbInState result;
1178  Datum *args;
1179  bool *nulls;
1180  Oid *types;
1181 
1182  /* build argument values to build the object */
1183  nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
1184 
1185  if (nargs < 0)
1186  PG_RETURN_NULL();
1187 
1188  if (nargs % 2 != 0)
1189  ereport(ERROR,
1190  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1191  errmsg("argument list must have even number of elements"),
1192  errhint("The arguments of jsonb_build_object() must consist of alternating keys and values.")));
1193 
1194  memset(&result, 0, sizeof(JsonbInState));
1195 
1196  result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1197 
1198  for (i = 0; i < nargs; i += 2)
1199  {
1200  /* process key */
1201  if (nulls[i])
1202  ereport(ERROR,
1203  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1204  errmsg("argument %d: key must not be null", i + 1)));
1205 
1206  add_jsonb(args[i], false, &result, types[i], true);
1207 
1208  /* process value */
1209  add_jsonb(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
1210  }
1211 
1212  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1213 
1215 }
1216 
1217 /*
1218  * degenerate case of jsonb_build_object where it gets 0 arguments.
1219  */
1220 Datum
1222 {
1223  JsonbInState result;
1224 
1225  memset(&result, 0, sizeof(JsonbInState));
1226 
1227  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1228  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1229 
1231 }
1232 
1233 /*
1234  * SQL function jsonb_build_array(variadic "any")
1235  */
1236 Datum
1238 {
1239  int nargs;
1240  int i;
1241  JsonbInState result;
1242  Datum *args;
1243  bool *nulls;
1244  Oid *types;
1245 
1246  /* build argument values to build the array */
1247  nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
1248 
1249  if (nargs < 0)
1250  PG_RETURN_NULL();
1251 
1252  memset(&result, 0, sizeof(JsonbInState));
1253 
1254  result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1255 
1256  for (i = 0; i < nargs; i++)
1257  add_jsonb(args[i], nulls[i], &result, types[i], false);
1258 
1259  result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1260 
1262 }
1263 
1264 /*
1265  * degenerate case of jsonb_build_array where it gets 0 arguments.
1266  */
1267 Datum
1269 {
1270  JsonbInState result;
1271 
1272  memset(&result, 0, sizeof(JsonbInState));
1273 
1274  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1275  result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1276 
1278 }
1279 
1280 
1281 /*
1282  * SQL function jsonb_object(text[])
1283  *
1284  * take a one or two dimensional array of text as name value pairs
1285  * for a jsonb object.
1286  *
1287  */
1288 Datum
1290 {
1291  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
1292  int ndims = ARR_NDIM(in_array);
1293  Datum *in_datums;
1294  bool *in_nulls;
1295  int in_count,
1296  count,
1297  i;
1298  JsonbInState result;
1299 
1300  memset(&result, 0, sizeof(JsonbInState));
1301 
1302  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1303 
1304  switch (ndims)
1305  {
1306  case 0:
1307  goto close_object;
1308  break;
1309 
1310  case 1:
1311  if ((ARR_DIMS(in_array)[0]) % 2)
1312  ereport(ERROR,
1313  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1314  errmsg("array must have even number of elements")));
1315  break;
1316 
1317  case 2:
1318  if ((ARR_DIMS(in_array)[1]) != 2)
1319  ereport(ERROR,
1320  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1321  errmsg("array must have two columns")));
1322  break;
1323 
1324  default:
1325  ereport(ERROR,
1326  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1327  errmsg("wrong number of array subscripts")));
1328  }
1329 
1330  deconstruct_array(in_array,
1331  TEXTOID, -1, false, 'i',
1332  &in_datums, &in_nulls, &in_count);
1333 
1334  count = in_count / 2;
1335 
1336  for (i = 0; i < count; ++i)
1337  {
1338  JsonbValue v;
1339  char *str;
1340  int len;
1341 
1342  if (in_nulls[i * 2])
1343  ereport(ERROR,
1344  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1345  errmsg("null value not allowed for object key")));
1346 
1347  str = TextDatumGetCString(in_datums[i * 2]);
1348  len = strlen(str);
1349 
1350  v.type = jbvString;
1351 
1352  v.val.string.len = len;
1353  v.val.string.val = str;
1354 
1355  (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1356 
1357  if (in_nulls[i * 2 + 1])
1358  {
1359  v.type = jbvNull;
1360  }
1361  else
1362  {
1363  str = TextDatumGetCString(in_datums[i * 2 + 1]);
1364  len = strlen(str);
1365 
1366  v.type = jbvString;
1367 
1368  v.val.string.len = len;
1369  v.val.string.val = str;
1370  }
1371 
1372  (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1373  }
1374 
1375  pfree(in_datums);
1376  pfree(in_nulls);
1377 
1378 close_object:
1379  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1380 
1382 }
1383 
1384 /*
1385  * SQL function jsonb_object(text[], text[])
1386  *
1387  * take separate name and value arrays of text to construct a jsonb object
1388  * pairwise.
1389  */
1390 Datum
1392 {
1393  ArrayType *key_array = PG_GETARG_ARRAYTYPE_P(0);
1394  ArrayType *val_array = PG_GETARG_ARRAYTYPE_P(1);
1395  int nkdims = ARR_NDIM(key_array);
1396  int nvdims = ARR_NDIM(val_array);
1397  Datum *key_datums,
1398  *val_datums;
1399  bool *key_nulls,
1400  *val_nulls;
1401  int key_count,
1402  val_count,
1403  i;
1404  JsonbInState result;
1405 
1406  memset(&result, 0, sizeof(JsonbInState));
1407 
1408  (void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1409 
1410  if (nkdims > 1 || nkdims != nvdims)
1411  ereport(ERROR,
1412  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1413  errmsg("wrong number of array subscripts")));
1414 
1415  if (nkdims == 0)
1416  goto close_object;
1417 
1418  deconstruct_array(key_array,
1419  TEXTOID, -1, false, 'i',
1420  &key_datums, &key_nulls, &key_count);
1421 
1422  deconstruct_array(val_array,
1423  TEXTOID, -1, false, 'i',
1424  &val_datums, &val_nulls, &val_count);
1425 
1426  if (key_count != val_count)
1427  ereport(ERROR,
1428  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1429  errmsg("mismatched array dimensions")));
1430 
1431  for (i = 0; i < key_count; ++i)
1432  {
1433  JsonbValue v;
1434  char *str;
1435  int len;
1436 
1437  if (key_nulls[i])
1438  ereport(ERROR,
1439  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1440  errmsg("null value not allowed for object key")));
1441 
1442  str = TextDatumGetCString(key_datums[i]);
1443  len = strlen(str);
1444 
1445  v.type = jbvString;
1446 
1447  v.val.string.len = len;
1448  v.val.string.val = str;
1449 
1450  (void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1451 
1452  if (val_nulls[i])
1453  {
1454  v.type = jbvNull;
1455  }
1456  else
1457  {
1458  str = TextDatumGetCString(val_datums[i]);
1459  len = strlen(str);
1460 
1461  v.type = jbvString;
1462 
1463  v.val.string.len = len;
1464  v.val.string.val = str;
1465  }
1466 
1467  (void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1468  }
1469 
1470  pfree(key_datums);
1471  pfree(key_nulls);
1472  pfree(val_datums);
1473  pfree(val_nulls);
1474 
1475 close_object:
1476  result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1477 
1479 }
1480 
1481 
1482 /*
1483  * shallow clone of a parse state, suitable for use in aggregate
1484  * final functions that will only append to the values rather than
1485  * change them.
1486  */
1487 static JsonbParseState *
1489 {
1490  JsonbParseState *result,
1491  *icursor,
1492  *ocursor;
1493 
1494  if (state == NULL)
1495  return NULL;
1496 
1497  result = palloc(sizeof(JsonbParseState));
1498  icursor = state;
1499  ocursor = result;
1500  for (;;)
1501  {
1502  ocursor->contVal = icursor->contVal;
1503  ocursor->size = icursor->size;
1504  icursor = icursor->next;
1505  if (icursor == NULL)
1506  break;
1507  ocursor->next = palloc(sizeof(JsonbParseState));
1508  ocursor = ocursor->next;
1509  }
1510  ocursor->next = NULL;
1511 
1512  return result;
1513 }
1514 
1515 
1516 /*
1517  * jsonb_agg aggregate function
1518  */
1519 Datum
1521 {
1522  MemoryContext oldcontext,
1523  aggcontext;
1525  JsonbInState elem;
1526  Datum val;
1527  JsonbInState *result;
1528  bool single_scalar = false;
1529  JsonbIterator *it;
1530  Jsonb *jbelem;
1531  JsonbValue v;
1533 
1534  if (!AggCheckCallContext(fcinfo, &aggcontext))
1535  {
1536  /* cannot be called directly because of internal-type argument */
1537  elog(ERROR, "jsonb_agg_transfn called in non-aggregate context");
1538  }
1539 
1540  /* set up the accumulator on the first go round */
1541 
1542  if (PG_ARGISNULL(0))
1543  {
1544  Oid arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1545 
1546  if (arg_type == InvalidOid)
1547  ereport(ERROR,
1548  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1549  errmsg("could not determine input data type")));
1550 
1551  oldcontext = MemoryContextSwitchTo(aggcontext);
1552  state = palloc(sizeof(JsonbAggState));
1553  result = palloc0(sizeof(JsonbInState));
1554  state->res = result;
1555  result->res = pushJsonbValue(&result->parseState,
1556  WJB_BEGIN_ARRAY, NULL);
1557  MemoryContextSwitchTo(oldcontext);
1558 
1559  jsonb_categorize_type(arg_type, &state->val_category,
1560  &state->val_output_func);
1561  }
1562  else
1563  {
1564  state = (JsonbAggState *) PG_GETARG_POINTER(0);
1565  result = state->res;
1566  }
1567 
1568  /* turn the argument into jsonb in the normal function context */
1569 
1570  val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
1571 
1572  memset(&elem, 0, sizeof(JsonbInState));
1573 
1574  datum_to_jsonb(val, PG_ARGISNULL(1), &elem, state->val_category,
1575  state->val_output_func, false);
1576 
1577  jbelem = JsonbValueToJsonb(elem.res);
1578 
1579  /* switch to the aggregate context for accumulation operations */
1580 
1581  oldcontext = MemoryContextSwitchTo(aggcontext);
1582 
1583  it = JsonbIteratorInit(&jbelem->root);
1584 
1585  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1586  {
1587  switch (type)
1588  {
1589  case WJB_BEGIN_ARRAY:
1590  if (v.val.array.rawScalar)
1591  single_scalar = true;
1592  else
1593  result->res = pushJsonbValue(&result->parseState,
1594  type, NULL);
1595  break;
1596  case WJB_END_ARRAY:
1597  if (!single_scalar)
1598  result->res = pushJsonbValue(&result->parseState,
1599  type, NULL);
1600  break;
1601  case WJB_BEGIN_OBJECT:
1602  case WJB_END_OBJECT:
1603  result->res = pushJsonbValue(&result->parseState,
1604  type, NULL);
1605  break;
1606  case WJB_ELEM:
1607  case WJB_KEY:
1608  case WJB_VALUE:
1609  if (v.type == jbvString)
1610  {
1611  /* copy string values in the aggregate context */
1612  char *buf = palloc(v.val.string.len + 1);
1613 
1614  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1615  v.val.string.val = buf;
1616  }
1617  else if (v.type == jbvNumeric)
1618  {
1619  /* same for numeric */
1620  v.val.numeric =
1622  NumericGetDatum(v.val.numeric)));
1623  }
1624  result->res = pushJsonbValue(&result->parseState,
1625  type, &v);
1626  break;
1627  default:
1628  elog(ERROR, "unknown jsonb iterator token type");
1629  }
1630  }
1631 
1632  MemoryContextSwitchTo(oldcontext);
1633 
1634  PG_RETURN_POINTER(state);
1635 }
1636 
1637 Datum
1639 {
1640  JsonbAggState *arg;
1641  JsonbInState result;
1642  Jsonb *out;
1643 
1644  /* cannot be called directly because of internal-type argument */
1645  Assert(AggCheckCallContext(fcinfo, NULL));
1646 
1647  if (PG_ARGISNULL(0))
1648  PG_RETURN_NULL(); /* returns null iff no input values */
1649 
1650  arg = (JsonbAggState *) PG_GETARG_POINTER(0);
1651 
1652  /*
1653  * We need to do a shallow clone of the argument in case the final
1654  * function is called more than once, so we avoid changing the argument. A
1655  * shallow clone is sufficient as we aren't going to change any of the
1656  * values, just add the final array end marker.
1657  */
1658 
1659  result.parseState = clone_parse_state(arg->res->parseState);
1660 
1661  result.res = pushJsonbValue(&result.parseState,
1662  WJB_END_ARRAY, NULL);
1663 
1664  out = JsonbValueToJsonb(result.res);
1665 
1666  PG_RETURN_POINTER(out);
1667 }
1668 
1669 /*
1670  * jsonb_object_agg aggregate function
1671  */
1672 Datum
1674 {
1675  MemoryContext oldcontext,
1676  aggcontext;
1677  JsonbInState elem;
1679  Datum val;
1680  JsonbInState *result;
1681  bool single_scalar;
1682  JsonbIterator *it;
1683  Jsonb *jbkey,
1684  *jbval;
1685  JsonbValue v;
1687 
1688  if (!AggCheckCallContext(fcinfo, &aggcontext))
1689  {
1690  /* cannot be called directly because of internal-type argument */
1691  elog(ERROR, "jsonb_object_agg_transfn called in non-aggregate context");
1692  }
1693 
1694  /* set up the accumulator on the first go round */
1695 
1696  if (PG_ARGISNULL(0))
1697  {
1698  Oid arg_type;
1699 
1700  oldcontext = MemoryContextSwitchTo(aggcontext);
1701  state = palloc(sizeof(JsonbAggState));
1702  result = palloc0(sizeof(JsonbInState));
1703  state->res = result;
1704  result->res = pushJsonbValue(&result->parseState,
1705  WJB_BEGIN_OBJECT, NULL);
1706  MemoryContextSwitchTo(oldcontext);
1707 
1708  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1709 
1710  if (arg_type == InvalidOid)
1711  ereport(ERROR,
1712  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1713  errmsg("could not determine input data type")));
1714 
1715  jsonb_categorize_type(arg_type, &state->key_category,
1716  &state->key_output_func);
1717 
1718  arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1719 
1720  if (arg_type == InvalidOid)
1721  ereport(ERROR,
1722  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1723  errmsg("could not determine input data type")));
1724 
1725  jsonb_categorize_type(arg_type, &state->val_category,
1726  &state->val_output_func);
1727  }
1728  else
1729  {
1730  state = (JsonbAggState *) PG_GETARG_POINTER(0);
1731  result = state->res;
1732  }
1733 
1734  /* turn the argument into jsonb in the normal function context */
1735 
1736  if (PG_ARGISNULL(1))
1737  ereport(ERROR,
1738  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1739  errmsg("field name must not be null")));
1740 
1741  val = PG_GETARG_DATUM(1);
1742 
1743  memset(&elem, 0, sizeof(JsonbInState));
1744 
1745  datum_to_jsonb(val, false, &elem, state->key_category,
1746  state->key_output_func, true);
1747 
1748  jbkey = JsonbValueToJsonb(elem.res);
1749 
1750  val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
1751 
1752  memset(&elem, 0, sizeof(JsonbInState));
1753 
1754  datum_to_jsonb(val, PG_ARGISNULL(2), &elem, state->val_category,
1755  state->val_output_func, false);
1756 
1757  jbval = JsonbValueToJsonb(elem.res);
1758 
1759  it = JsonbIteratorInit(&jbkey->root);
1760 
1761  /* switch to the aggregate context for accumulation operations */
1762 
1763  oldcontext = MemoryContextSwitchTo(aggcontext);
1764 
1765  /*
1766  * keys should be scalar, and we should have already checked for that
1767  * above when calling datum_to_jsonb, so we only need to look for these
1768  * things.
1769  */
1770 
1771  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1772  {
1773  switch (type)
1774  {
1775  case WJB_BEGIN_ARRAY:
1776  if (!v.val.array.rawScalar)
1777  elog(ERROR, "unexpected structure for key");
1778  break;
1779  case WJB_ELEM:
1780  if (v.type == jbvString)
1781  {
1782  /* copy string values in the aggregate context */
1783  char *buf = palloc(v.val.string.len + 1);
1784 
1785  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1786  v.val.string.val = buf;
1787  }
1788  else
1789  {
1790  ereport(ERROR,
1791  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1792  errmsg("object keys must be strings")));
1793  }
1794  result->res = pushJsonbValue(&result->parseState,
1795  WJB_KEY, &v);
1796  break;
1797  case WJB_END_ARRAY:
1798  break;
1799  default:
1800  elog(ERROR, "unexpected structure for key");
1801  break;
1802  }
1803  }
1804 
1805  it = JsonbIteratorInit(&jbval->root);
1806 
1807  single_scalar = false;
1808 
1809  /*
1810  * values can be anything, including structured and null, so we treat them
1811  * as in json_agg_transfn, except that single scalars are always pushed as
1812  * WJB_VALUE items.
1813  */
1814 
1815  while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1816  {
1817  switch (type)
1818  {
1819  case WJB_BEGIN_ARRAY:
1820  if (v.val.array.rawScalar)
1821  single_scalar = true;
1822  else
1823  result->res = pushJsonbValue(&result->parseState,
1824  type, NULL);
1825  break;
1826  case WJB_END_ARRAY:
1827  if (!single_scalar)
1828  result->res = pushJsonbValue(&result->parseState,
1829  type, NULL);
1830  break;
1831  case WJB_BEGIN_OBJECT:
1832  case WJB_END_OBJECT:
1833  result->res = pushJsonbValue(&result->parseState,
1834  type, NULL);
1835  break;
1836  case WJB_ELEM:
1837  case WJB_KEY:
1838  case WJB_VALUE:
1839  if (v.type == jbvString)
1840  {
1841  /* copy string values in the aggregate context */
1842  char *buf = palloc(v.val.string.len + 1);
1843 
1844  snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1845  v.val.string.val = buf;
1846  }
1847  else if (v.type == jbvNumeric)
1848  {
1849  /* same for numeric */
1850  v.val.numeric =
1852  NumericGetDatum(v.val.numeric)));
1853  }
1854  result->res = pushJsonbValue(&result->parseState,
1855  single_scalar ? WJB_VALUE : type,
1856  &v);
1857  break;
1858  default:
1859  elog(ERROR, "unknown jsonb iterator token type");
1860  }
1861  }
1862 
1863  MemoryContextSwitchTo(oldcontext);
1864 
1865  PG_RETURN_POINTER(state);
1866 }
1867 
1868 Datum
1870 {
1871  JsonbAggState *arg;
1872  JsonbInState result;
1873  Jsonb *out;
1874 
1875  /* cannot be called directly because of internal-type argument */
1876  Assert(AggCheckCallContext(fcinfo, NULL));
1877 
1878  if (PG_ARGISNULL(0))
1879  PG_RETURN_NULL(); /* returns null iff no input values */
1880 
1881  arg = (JsonbAggState *) PG_GETARG_POINTER(0);
1882 
1883  /*
1884  * We need to do a shallow clone of the argument's res field in case the
1885  * final function is called more than once, so we avoid changing the
1886  * aggregate state value. A shallow clone is sufficient as we aren't
1887  * going to change any of the values, just add the final object end
1888  * marker.
1889  */
1890 
1891  result.parseState = clone_parse_state(arg->res->parseState);
1892 
1893  result.res = pushJsonbValue(&result.parseState,
1894  WJB_END_OBJECT, NULL);
1895 
1896  out = JsonbValueToJsonb(result.res);
1897 
1898  PG_RETURN_POINTER(out);
1899 }
#define MAXDATELEN
Definition: datetime.h:203
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:3884
json_struct_action array_end
Definition: jsonapi.h:88
#define RECORDARRAYOID
Definition: pg_type.h:682
#define TIMESTAMPTZOID
Definition: pg_type.h:525
static void array_to_jsonb_internal(Datum array, JsonbInState *result)
Definition: jsonb.c:999
signed short int16
Definition: c.h:283
JsonbParseState * parseState
Definition: jsonb.c:34
JsonbValue * res
Definition: jsonb.c:35
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
static void jsonb_in_object_end(void *pstate)
Definition: jsonb.c:274
#define DATEOID
Definition: pg_type.h:511
#define DatumGetDateADT(X)
Definition: date.h:52
#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:1087
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2646
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Definition: jsonb.h:215
Datum numeric_uplus(PG_FUNCTION_ARGS)
Definition: numeric.c:1158
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:1476
static char * JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
Definition: jsonb.c:447
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2397
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1618
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:1173
Datum jsonb_object(PG_FUNCTION_ARGS)
Definition: jsonb.c:1289
int32 DateADT
Definition: date.h:22
static void jsonb_in_array_start(void *pstate)
Definition: jsonb.c:282
#define TEXTOID
Definition: pg_type.h:324
#define VARSIZE(PTR)
Definition: postgres.h:304
#define DatumGetJsonbP(d)
Definition: jsonb.h:68
int64 timestamp
Oid get_element_type(Oid typid)
Definition: lsyscache.c:2498
int64 TimestampTz
Definition: timestamp.h:39
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2021
#define PointerGetDatum(X)
Definition: postgres.h:562
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:233
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define NUMERICOID
Definition: pg_type.h:554
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
#define JSONOID
Definition: pg_type.h:356
char * pstrdup(const char *in)
Definition: mcxt.c:1076
char * val
Definition: jsonb.h:259
static JsonbParseState * clone_parse_state(JsonbParseState *state)
Definition: jsonb.c:1488
#define NumericGetDatum(X)
Definition: numeric.h:51
JsonbInState * res
Definition: jsonb.c:57
#define DatumGetTextPP(X)
Definition: fmgr.h:256
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1758
Definition: jsonb.h:234
StringInfo makeStringInfo(void)
Definition: stringinfo.c:28
StringInfoData * StringInfo
Definition: stringinfo.h:43
int ArrayGetNItems(int ndim, const int *dims)
Definition: arrayutils.c:75
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:651
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:1119
Definition: jsonb.h:22
#define INT4OID
Definition: pg_type.h:316
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
#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:241
Definition: jsonb.h:231
long date
Definition: pgtypes_date.h:8
void EncodeSpecialTimestamp(Timestamp dt, char *str)
Definition: timestamp.c:1523
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:330
#define JB_ROOT_IS_SCALAR(jbp_)
Definition: jsonb.h:223
Definition: pgtime.h:25
unsigned int Oid
Definition: postgres_ext.h:31
struct JsonbParseState * next
Definition: jsonb.h:308
#define OidIsValid(objectId)
Definition: c.h:576
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:259
int natts
Definition: tupdesc.h:79
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:284
char * JsonbToCStringIndent(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:438
static void jsonb_in_array_end(void *pstate)
Definition: jsonb.c:290
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:460
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:700
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
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:122
void pfree(void *pointer)
Definition: mcxt.c:949
Datum jsonb_send(PG_FUNCTION_ARGS)
Definition: jsonb.c:148
#define TIMESTAMPOID
Definition: pg_type.h:519
Datum jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1869
#define ERROR
Definition: elog.h:43
Datum jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1673
#define DatumGetCString(X)
Definition: postgres.h:572
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1904
Datum jsonb_build_object_noargs(PG_FUNCTION_ARGS)
Definition: jsonb.c:1221
#define ARR_DIMS(a)
Definition: array.h:279
#define JB_ROOT_IS_ARRAY(jbp_)
Definition: jsonb.h:225
#define DATE_NOT_FINITE(j)
Definition: date.h:42
void pg_parse_json(JsonLexContext *lex, JsonSemAction *sem)
Definition: json.c:332
#define OidFunctionCall1(functionId, arg1)
Definition: fmgr.h:623
#define INT2OID
Definition: pg_type.h:308
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
int tm_mday
Definition: pgtime.h:30
static char * buf
Definition: pg_test_fsync.c:67
Datum to_jsonb(PG_FUNCTION_ARGS)
Definition: jsonb.c:1146
int tm_mon
Definition: pgtime.h:31
void check_stack_depth(void)
Definition: postgres.c:3150
#define DatumGetTimestampTz(X)
Definition: timestamp.h:28
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define CStringGetDatum(X)
Definition: postgres.h:584
#define DatumGetBool(X)
Definition: postgres.h:399
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:264
#define JSONBOID
Definition: pg_type.h:638
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:3999
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
static void jsonb_categorize_type(Oid typoid, JsonbTypeCategory *tcategory, Oid *outfuncoid)
Definition: jsonb.c:592
void EncodeSpecialDate(DateADT dt, char *str)
Definition: date.c:299
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:569
Definition: jsonb.h:23
int32 fsec_t
Definition: timestamp.h:41
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2405
Datum jsonb_recv(PG_FUNCTION_ARGS)
Definition: jsonb.c:113
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:967
#define ereport(elevel, rest)
Definition: elog.h:122
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:317
JsonbIteratorToken
Definition: jsonb.h:20
struct JsonbAggState JsonbAggState
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:589
int64 Timestamp
Definition: timestamp.h:38
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:774
#define TextDatumGetCString(d)
Definition: builtins.h:92
#define FLOAT4OID
Definition: pg_type.h:416
#define ANYARRAYOID
Definition: pg_type.h:688
void * palloc0(Size size)
Definition: mcxt.c:877
static void composite_to_jsonb(Datum composite, JsonbInState *result)
Definition: jsonb.c:1047
uintptr_t Datum
Definition: postgres.h:372
Datum jsonb_object_two_arg(PG_FUNCTION_ARGS)
Definition: jsonb.c:1391
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:450
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:571
JsonbTypeCategory
Definition: jsonb.c:39
#define InvalidOid
Definition: postgres_ext.h:36
Datum jsonb_agg_transfn(PG_FUNCTION_ARGS)
Definition: jsonb.c:1520
#define INT8OID
Definition: pg_type.h:304
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define Assert(condition)
Definition: c.h:670
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:322
char * JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
Definition: jsonb.c:429
struct JsonbInState JsonbInState
#define FLOAT8OID
Definition: pg_type.h:419
JsonLexContext * makeJsonLexContextCstringLen(char *json, int len, bool need_escapes)
Definition: json.c:309
int AggCheckCallContext(FunctionCallInfo fcinfo, MemoryContext *aggcontext)
Definition: nodeAgg.c:4116
Datum jsonb_build_array(PG_FUNCTION_ARGS)
Definition: jsonb.c:1237
#define BOOLOID
Definition: pg_type.h:288
#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
Datum jsonb_build_array_noargs(PG_FUNCTION_ARGS)
Definition: jsonb.c:1268
#define USE_XSD_DATES
Definition: miscadmin.h:214
int tm_year
Definition: pgtime.h:32
Datum jsonb_in(PG_FUNCTION_ARGS)
Definition: jsonb.c:97
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1742
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
CoercionPathType find_coercion_pathway(Oid targetTypeId, Oid sourceTypeId, CoercionContext ccontext, Oid *funcid)
Oid val_output_func
Definition: jsonb.c:61
int i
#define NameStr(name)
Definition: c.h:547
void * arg
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
Definition: c.h:487
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:163
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:1638
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:121
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2271
#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:305
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 DatumGetTimestamp(X)
Definition: timestamp.h:27
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:444
#define DatumGetArrayTypeP(X)
Definition: array.h:246