1 /*-------------------------------------------------------------------------
2  *
3  * jsonb.c
4  *		I/O routines for jsonb type
5  *
6  * Copyright (c) 2014-2016, 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 {
34 	JsonbParseState *parseState;
35 	JsonbValue *res;
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 */
53 } JsonbTypeCategory;
54 
55 typedef struct JsonbAggState
56 {
57 	JsonbInState *res;
58 	JsonbTypeCategory key_category;
59 	Oid			key_output_func;
60 	JsonbTypeCategory val_category;
61 	Oid			val_output_func;
62 } JsonbAggState;
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);
89 static JsonbParseState *clone_parse_state(JsonbParseState *state);
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
jsonb_in(PG_FUNCTION_ARGS)97 jsonb_in(PG_FUNCTION_ARGS)
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
jsonb_recv(PG_FUNCTION_ARGS)113 jsonb_recv(PG_FUNCTION_ARGS)
114 {
115 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
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
jsonb_out(PG_FUNCTION_ARGS)132 jsonb_out(PG_FUNCTION_ARGS)
133 {
134 	Jsonb	   *jb = PG_GETARG_JSONB(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
jsonb_send(PG_FUNCTION_ARGS)148 jsonb_send(PG_FUNCTION_ARGS)
149 {
150 	Jsonb	   *jb = PG_GETARG_JSONB(0);
151 	StringInfoData buf;
152 	StringInfo	jtext = makeStringInfo();
153 	int			version = 1;
154 
155 	(void) JsonbToCString(jtext, &jb->root, VARSIZE(jb));
156 
157 	pq_begintypsend(&buf);
158 	pq_sendint(&buf, version, 1);
159 	pq_sendtext(&buf, jtext->data, jtext->len);
160 	pfree(jtext->data);
161 	pfree(jtext);
162 
163 	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
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
jsonb_typeof(PG_FUNCTION_ARGS)173 jsonb_typeof(PG_FUNCTION_ARGS)
174 {
175 	Jsonb	   *in = PG_GETARG_JSONB(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 	{
186 		Assert(JB_ROOT_IS_SCALAR(in));
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 
216 	PG_RETURN_TEXT_P(cstring_to_text(result));
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
jsonb_from_cstring(char * json,int len)227 jsonb_from_cstring(char *json, int len)
228 {
229 	JsonLexContext *lex;
230 	JsonbInState state;
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 
239 	sem.object_start = jsonb_in_object_start;
240 	sem.array_start = jsonb_in_array_start;
241 	sem.object_end = jsonb_in_object_end;
242 	sem.array_end = jsonb_in_array_end;
243 	sem.scalar = jsonb_in_scalar;
244 	sem.object_field_start = jsonb_in_object_field_start;
245 
246 	pg_parse_json(lex, &sem);
247 
248 	/* after parsing, the item member has the composed jsonb structure */
249 	PG_RETURN_POINTER(JsonbValueToJsonb(state.res));
250 }
251 
252 static size_t
checkStringLen(size_t len)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.",
260 						   JENTRY_OFFLENMASK)));
261 
262 	return len;
263 }
264 
265 static void
jsonb_in_object_start(void * pstate)266 jsonb_in_object_start(void *pstate)
267 {
268 	JsonbInState *_state = (JsonbInState *) pstate;
269 
270 	_state->res = pushJsonbValue(&_state->parseState, WJB_BEGIN_OBJECT, NULL);
271 }
272 
273 static void
jsonb_in_object_end(void * pstate)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
jsonb_in_array_start(void * pstate)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
jsonb_in_array_end(void * pstate)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
jsonb_in_object_field_start(void * pstate,char * fname,bool isnull)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
jsonb_put_escaped_value(StringInfo out,JsonbValue * scalarVal)312 jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal)
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:
323 			appendStringInfoString(out,
324 							 DatumGetCString(DirectFunctionCall1(numeric_out,
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
jsonb_in_scalar(void * pstate,char * token,JsonTokenType tokentype)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;
364 			v.val.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(token), 0, -1));
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 *
JsonbToCString(StringInfo out,JsonbContainer * in,int estimated_len)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 *
JsonbToCStringIndent(StringInfo out,JsonbContainer * in,int estimated_len)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 *
JsonbToCStringWorker(StringInfo out,JsonbContainer * in,int estimated_len,bool indent)447 JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent)
448 {
449 	bool		first = true;
450 	JsonbIterator *it;
451 	JsonbValue	v;
452 	JsonbIteratorToken type = WJB_DONE;
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
add_indent(StringInfo out,bool indent,int level)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
jsonb_categorize_type(Oid typoid,JsonbTypeCategory * tcategory,Oid * outfuncoid)592 jsonb_categorize_type(Oid typoid,
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)))
649 				*tcategory = JSONBTYPE_ARRAY;
650 			else if (type_is_rowtype(typoid))
651 				*tcategory = JSONBTYPE_COMPOSITE;
652 			else
653 			{
654 				/* It's probably the general case ... */
655 				*tcategory = JSONBTYPE_OTHER;
656 
657 				/*
658 				 * but first let's look for a cast to json (note: not to
659 				 * jsonb) if it's not built-in.
660 				 */
661 				if (typoid >= FirstNormalObjectId)
662 				{
663 					Oid			castfunc;
664 					CoercionPathType ctype;
665 
666 					ctype = find_coercion_pathway(JSONOID, typoid,
667 											   COERCION_EXPLICIT, &castfunc);
668 					if (ctype == COERCION_PATH_FUNC && OidIsValid(castfunc))
669 					{
670 						*tcategory = JSONBTYPE_JSONCAST;
671 						*outfuncoid = castfunc;
672 					}
673 					else
674 					{
675 						/* not a cast type, so just get the usual output func */
676 						getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
677 					}
678 				}
679 				else
680 				{
681 					/* any other builtin type */
682 					getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
683 				}
684 				break;
685 			}
686 	}
687 }
688 
689 /*
690  * Turn a Datum into jsonb, adding it to the result JsonbInState.
691  *
692  * tcategory and outfuncoid are from a previous call to json_categorize_type,
693  * except that if is_null is true then they can be invalid.
694  *
695  * If key_scalar is true, the value is stored as a key, so insist
696  * it's of an acceptable type, and force it to be a jbvString.
697  */
698 static void
datum_to_jsonb(Datum val,bool is_null,JsonbInState * result,JsonbTypeCategory tcategory,Oid outfuncoid,bool key_scalar)699 datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
700 			   JsonbTypeCategory tcategory, Oid outfuncoid,
701 			   bool key_scalar)
702 {
703 	char	   *outputstr;
704 	bool		numeric_error;
705 	JsonbValue	jb;
706 	bool		scalar_jsonb = false;
707 
708 	check_stack_depth();
709 
710 	/* Convert val to a JsonbValue in jb (in most cases) */
711 	if (is_null)
712 	{
713 		Assert(!key_scalar);
714 		jb.type = jbvNull;
715 	}
716 	else if (key_scalar &&
717 			 (tcategory == JSONBTYPE_ARRAY ||
718 			  tcategory == JSONBTYPE_COMPOSITE ||
719 			  tcategory == JSONBTYPE_JSON ||
720 			  tcategory == JSONBTYPE_JSONB ||
721 			  tcategory == JSONBTYPE_JSONCAST))
722 	{
723 		ereport(ERROR,
724 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
725 		 errmsg("key value must be scalar, not array, composite, or json")));
726 	}
727 	else
728 	{
729 		if (tcategory == JSONBTYPE_JSONCAST)
730 			val = OidFunctionCall1(outfuncoid, val);
731 
732 		switch (tcategory)
733 		{
734 			case JSONBTYPE_ARRAY:
735 				array_to_jsonb_internal(val, result);
736 				break;
737 			case JSONBTYPE_COMPOSITE:
738 				composite_to_jsonb(val, result);
739 				break;
740 			case JSONBTYPE_BOOL:
741 				if (key_scalar)
742 				{
743 					outputstr = DatumGetBool(val) ? "true" : "false";
744 					jb.type = jbvString;
745 					jb.val.string.len = strlen(outputstr);
746 					jb.val.string.val = outputstr;
747 				}
748 				else
749 				{
750 					jb.type = jbvBool;
751 					jb.val.boolean = DatumGetBool(val);
752 				}
753 				break;
754 			case JSONBTYPE_NUMERIC:
755 				outputstr = OidOutputFunctionCall(outfuncoid, val);
756 				if (key_scalar)
757 				{
758 					/* always quote keys */
759 					jb.type = jbvString;
760 					jb.val.string.len = strlen(outputstr);
761 					jb.val.string.val = outputstr;
762 				}
763 				else
764 				{
765 					/*
766 					 * Make it numeric if it's a valid JSON number, otherwise
767 					 * a string. Invalid numeric output will always have an
768 					 * 'N' or 'n' in it (I think).
769 					 */
770 					numeric_error = (strchr(outputstr, 'N') != NULL ||
771 									 strchr(outputstr, 'n') != NULL);
772 					if (!numeric_error)
773 					{
774 						jb.type = jbvNumeric;
775 						jb.val.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(outputstr), 0, -1));
776 
777 						pfree(outputstr);
778 					}
779 					else
780 					{
781 						jb.type = jbvString;
782 						jb.val.string.len = strlen(outputstr);
783 						jb.val.string.val = outputstr;
784 					}
785 				}
786 				break;
787 			case JSONBTYPE_DATE:
788 				{
789 					DateADT		date;
790 					struct pg_tm tm;
791 					char		buf[MAXDATELEN + 1];
792 
793 					date = DatumGetDateADT(val);
794 					/* Same as date_out(), but forcing DateStyle */
795 					if (DATE_NOT_FINITE(date))
796 						EncodeSpecialDate(date, buf);
797 					else
798 					{
799 						j2date(date + POSTGRES_EPOCH_JDATE,
800 							   &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
801 						EncodeDateOnly(&tm, USE_XSD_DATES, buf);
802 					}
803 					jb.type = jbvString;
804 					jb.val.string.len = strlen(buf);
805 					jb.val.string.val = pstrdup(buf);
806 				}
807 				break;
808 			case JSONBTYPE_TIMESTAMP:
809 				{
810 					Timestamp	timestamp;
811 					struct pg_tm tm;
812 					fsec_t		fsec;
813 					char		buf[MAXDATELEN + 1];
814 
815 					timestamp = DatumGetTimestamp(val);
816 					/* Same as timestamp_out(), but forcing DateStyle */
817 					if (TIMESTAMP_NOT_FINITE(timestamp))
818 						EncodeSpecialTimestamp(timestamp, buf);
819 					else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
820 						EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
821 					else
822 						ereport(ERROR,
823 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
824 								 errmsg("timestamp out of range")));
825 					jb.type = jbvString;
826 					jb.val.string.len = strlen(buf);
827 					jb.val.string.val = pstrdup(buf);
828 				}
829 				break;
830 			case JSONBTYPE_TIMESTAMPTZ:
831 				{
832 					TimestampTz timestamp;
833 					struct pg_tm tm;
834 					int			tz;
835 					fsec_t		fsec;
836 					const char *tzn = NULL;
837 					char		buf[MAXDATELEN + 1];
838 
839 					timestamp = DatumGetTimestampTz(val);
840 					/* Same as timestamptz_out(), but forcing DateStyle */
841 					if (TIMESTAMP_NOT_FINITE(timestamp))
842 						EncodeSpecialTimestamp(timestamp, buf);
843 					else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
844 						EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
845 					else
846 						ereport(ERROR,
847 								(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
848 								 errmsg("timestamp out of range")));
849 					jb.type = jbvString;
850 					jb.val.string.len = strlen(buf);
851 					jb.val.string.val = pstrdup(buf);
852 				}
853 				break;
854 			case JSONBTYPE_JSONCAST:
855 			case JSONBTYPE_JSON:
856 				{
857 					/* parse the json right into the existing result object */
858 					JsonLexContext *lex;
859 					JsonSemAction sem;
860 					text	   *json = DatumGetTextP(val);
861 
862 					lex = makeJsonLexContext(json, true);
863 
864 					memset(&sem, 0, sizeof(sem));
865 
866 					sem.semstate = (void *) result;
867 
868 					sem.object_start = jsonb_in_object_start;
869 					sem.array_start = jsonb_in_array_start;
870 					sem.object_end = jsonb_in_object_end;
871 					sem.array_end = jsonb_in_array_end;
872 					sem.scalar = jsonb_in_scalar;
873 					sem.object_field_start = jsonb_in_object_field_start;
874 
875 					pg_parse_json(lex, &sem);
876 
877 				}
878 				break;
879 			case JSONBTYPE_JSONB:
880 				{
881 					Jsonb	   *jsonb = DatumGetJsonb(val);
882 					JsonbIterator *it;
883 
884 					it = JsonbIteratorInit(&jsonb->root);
885 
886 					if (JB_ROOT_IS_SCALAR(jsonb))
887 					{
888 						(void) JsonbIteratorNext(&it, &jb, true);
889 						Assert(jb.type == jbvArray);
890 						(void) JsonbIteratorNext(&it, &jb, true);
891 						scalar_jsonb = true;
892 					}
893 					else
894 					{
895 						JsonbIteratorToken type;
896 
897 						while ((type = JsonbIteratorNext(&it, &jb, false))
898 							   != WJB_DONE)
899 						{
900 							if (type == WJB_END_ARRAY || type == WJB_END_OBJECT ||
901 								type == WJB_BEGIN_ARRAY || type == WJB_BEGIN_OBJECT)
902 								result->res = pushJsonbValue(&result->parseState,
903 															 type, NULL);
904 							else
905 								result->res = pushJsonbValue(&result->parseState,
906 															 type, &jb);
907 						}
908 					}
909 				}
910 				break;
911 			default:
912 				outputstr = OidOutputFunctionCall(outfuncoid, val);
913 				jb.type = jbvString;
914 				jb.val.string.len = checkStringLen(strlen(outputstr));
915 				jb.val.string.val = outputstr;
916 				break;
917 		}
918 	}
919 
920 	/* Now insert jb into result, unless we did it recursively */
921 	if (!is_null && !scalar_jsonb &&
922 		tcategory >= JSONBTYPE_JSON && tcategory <= JSONBTYPE_JSONCAST)
923 	{
924 		/* work has been done recursively */
925 		return;
926 	}
927 	else if (result->parseState == NULL)
928 	{
929 		/* single root scalar */
930 		JsonbValue	va;
931 
932 		va.type = jbvArray;
933 		va.val.array.rawScalar = true;
934 		va.val.array.nElems = 1;
935 
936 		result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, &va);
937 		result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
938 		result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
939 	}
940 	else
941 	{
942 		JsonbValue *o = &result->parseState->contVal;
943 
944 		switch (o->type)
945 		{
946 			case jbvArray:
947 				result->res = pushJsonbValue(&result->parseState, WJB_ELEM, &jb);
948 				break;
949 			case jbvObject:
950 				result->res = pushJsonbValue(&result->parseState,
951 											 key_scalar ? WJB_KEY : WJB_VALUE,
952 											 &jb);
953 				break;
954 			default:
955 				elog(ERROR, "unexpected parent of nested structure");
956 		}
957 	}
958 }
959 
960 /*
961  * Process a single dimension of an array.
962  * If it's the innermost dimension, output the values, otherwise call
963  * ourselves recursively to process the next dimension.
964  */
965 static void
array_dim_to_jsonb(JsonbInState * result,int dim,int ndims,int * dims,Datum * vals,bool * nulls,int * valcount,JsonbTypeCategory tcategory,Oid outfuncoid)966 array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *vals,
967 				   bool *nulls, int *valcount, JsonbTypeCategory tcategory,
968 				   Oid outfuncoid)
969 {
970 	int			i;
971 
972 	Assert(dim < ndims);
973 
974 	result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
975 
976 	for (i = 1; i <= dims[dim]; i++)
977 	{
978 		if (dim + 1 == ndims)
979 		{
980 			datum_to_jsonb(vals[*valcount], nulls[*valcount], result, tcategory,
981 						   outfuncoid, false);
982 			(*valcount)++;
983 		}
984 		else
985 		{
986 			array_dim_to_jsonb(result, dim + 1, ndims, dims, vals, nulls,
987 							   valcount, tcategory, outfuncoid);
988 		}
989 	}
990 
991 	result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
992 }
993 
994 /*
995  * Turn an array into JSON.
996  */
997 static void
array_to_jsonb_internal(Datum array,JsonbInState * result)998 array_to_jsonb_internal(Datum array, JsonbInState *result)
999 {
1000 	ArrayType  *v = DatumGetArrayTypeP(array);
1001 	Oid			element_type = ARR_ELEMTYPE(v);
1002 	int		   *dim;
1003 	int			ndim;
1004 	int			nitems;
1005 	int			count = 0;
1006 	Datum	   *elements;
1007 	bool	   *nulls;
1008 	int16		typlen;
1009 	bool		typbyval;
1010 	char		typalign;
1011 	JsonbTypeCategory tcategory;
1012 	Oid			outfuncoid;
1013 
1014 	ndim = ARR_NDIM(v);
1015 	dim = ARR_DIMS(v);
1016 	nitems = ArrayGetNItems(ndim, dim);
1017 
1018 	if (nitems <= 0)
1019 	{
1020 		result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_ARRAY, NULL);
1021 		result->res = pushJsonbValue(&result->parseState, WJB_END_ARRAY, NULL);
1022 		return;
1023 	}
1024 
1025 	get_typlenbyvalalign(element_type,
1026 						 &typlen, &typbyval, &typalign);
1027 
1028 	jsonb_categorize_type(element_type,
1029 						  &tcategory, &outfuncoid);
1030 
1031 	deconstruct_array(v, element_type, typlen, typbyval,
1032 					  typalign, &elements, &nulls,
1033 					  &nitems);
1034 
1035 	array_dim_to_jsonb(result, 0, ndim, dim, elements, nulls, &count, tcategory,
1036 					   outfuncoid);
1037 
1038 	pfree(elements);
1039 	pfree(nulls);
1040 }
1041 
1042 /*
1043  * Turn a composite / record into JSON.
1044  */
1045 static void
composite_to_jsonb(Datum composite,JsonbInState * result)1046 composite_to_jsonb(Datum composite, JsonbInState *result)
1047 {
1048 	HeapTupleHeader td;
1049 	Oid			tupType;
1050 	int32		tupTypmod;
1051 	TupleDesc	tupdesc;
1052 	HeapTupleData tmptup,
1053 			   *tuple;
1054 	int			i;
1055 
1056 	td = DatumGetHeapTupleHeader(composite);
1057 
1058 	/* Extract rowtype info and find a tupdesc */
1059 	tupType = HeapTupleHeaderGetTypeId(td);
1060 	tupTypmod = HeapTupleHeaderGetTypMod(td);
1061 	tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
1062 
1063 	/* Build a temporary HeapTuple control structure */
1064 	tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
1065 	tmptup.t_data = td;
1066 	tuple = &tmptup;
1067 
1068 	result->res = pushJsonbValue(&result->parseState, WJB_BEGIN_OBJECT, NULL);
1069 
1070 	for (i = 0; i < tupdesc->natts; i++)
1071 	{
1072 		Datum		val;
1073 		bool		isnull;
1074 		char	   *attname;
1075 		JsonbTypeCategory tcategory;
1076 		Oid			outfuncoid;
1077 		JsonbValue	v;
1078 
1079 		if (tupdesc->attrs[i]->attisdropped)
1080 			continue;
1081 
1082 		attname = NameStr(tupdesc->attrs[i]->attname);
1083 
1084 		v.type = jbvString;
1085 		/* don't need checkStringLen here - can't exceed maximum name length */
1086 		v.val.string.len = strlen(attname);
1087 		v.val.string.val = attname;
1088 
1089 		result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
1090 
1091 		val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
1092 
1093 		if (isnull)
1094 		{
1095 			tcategory = JSONBTYPE_NULL;
1096 			outfuncoid = InvalidOid;
1097 		}
1098 		else
1099 			jsonb_categorize_type(tupdesc->attrs[i]->atttypid,
1100 								  &tcategory, &outfuncoid);
1101 
1102 		datum_to_jsonb(val, isnull, result, tcategory, outfuncoid, false);
1103 	}
1104 
1105 	result->res = pushJsonbValue(&result->parseState, WJB_END_OBJECT, NULL);
1106 	ReleaseTupleDesc(tupdesc);
1107 }
1108 
1109 /*
1110  * Append JSON text for "val" to "result".
1111  *
1112  * This is just a thin wrapper around datum_to_jsonb.  If the same type will be
1113  * printed many times, avoid using this; better to do the jsonb_categorize_type
1114  * lookups only once.
1115  */
1116 
1117 static void
add_jsonb(Datum val,bool is_null,JsonbInState * result,Oid val_type,bool key_scalar)1118 add_jsonb(Datum val, bool is_null, JsonbInState *result,
1119 		  Oid val_type, bool key_scalar)
1120 {
1121 	JsonbTypeCategory tcategory;
1122 	Oid			outfuncoid;
1123 
1124 	if (val_type == InvalidOid)
1125 		ereport(ERROR,
1126 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1127 				 errmsg("could not determine input data type")));
1128 
1129 	if (is_null)
1130 	{
1131 		tcategory = JSONBTYPE_NULL;
1132 		outfuncoid = InvalidOid;
1133 	}
1134 	else
1135 		jsonb_categorize_type(val_type,
1136 							  &tcategory, &outfuncoid);
1137 
1138 	datum_to_jsonb(val, is_null, result, tcategory, outfuncoid, key_scalar);
1139 }
1140 
1141 /*
1142  * SQL function to_jsonb(anyvalue)
1143  */
1144 Datum
to_jsonb(PG_FUNCTION_ARGS)1145 to_jsonb(PG_FUNCTION_ARGS)
1146 {
1147 	Datum		val = PG_GETARG_DATUM(0);
1148 	Oid			val_type = get_fn_expr_argtype(fcinfo->flinfo, 0);
1149 	JsonbInState result;
1150 	JsonbTypeCategory tcategory;
1151 	Oid			outfuncoid;
1152 
1153 	if (val_type == InvalidOid)
1154 		ereport(ERROR,
1155 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1156 				 errmsg("could not determine input data type")));
1157 
1158 	jsonb_categorize_type(val_type,
1159 						  &tcategory, &outfuncoid);
1160 
1161 	memset(&result, 0, sizeof(JsonbInState));
1162 
1163 	datum_to_jsonb(val, false, &result, tcategory, outfuncoid, false);
1164 
1165 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1166 }
1167 
1168 /*
1169  * SQL function jsonb_build_object(variadic "any")
1170  */
1171 Datum
jsonb_build_object(PG_FUNCTION_ARGS)1172 jsonb_build_object(PG_FUNCTION_ARGS)
1173 {
1174 	int			nargs;
1175 	int			i;
1176 	JsonbInState result;
1177 	Datum	   *args;
1178 	bool	   *nulls;
1179 	Oid		   *types;
1180 
1181 	/* build argument values to build the object */
1182 	nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
1183 
1184 	if (nargs < 0)
1185 		PG_RETURN_NULL();
1186 
1187 	if (nargs % 2 != 0)
1188 		ereport(ERROR,
1189 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1190 				 errmsg("argument list must have even number of elements"),
1191 				 errhint("The arguments of jsonb_build_object() must consist of alternating keys and values.")));
1192 
1193 	memset(&result, 0, sizeof(JsonbInState));
1194 
1195 	result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1196 
1197 	for (i = 0; i < nargs; i += 2)
1198 	{
1199 		/* process key */
1200 		if (nulls[i])
1201 			ereport(ERROR,
1202 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1203 					 errmsg("argument %d: key must not be null", i + 1)));
1204 
1205 		add_jsonb(args[i], false, &result, types[i], true);
1206 
1207 		/* process value */
1208 		add_jsonb(args[i + 1], nulls[i + 1], &result, types[i + 1], false);
1209 	}
1210 
1211 	result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1212 
1213 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1214 }
1215 
1216 /*
1217  * degenerate case of jsonb_build_object where it gets 0 arguments.
1218  */
1219 Datum
jsonb_build_object_noargs(PG_FUNCTION_ARGS)1220 jsonb_build_object_noargs(PG_FUNCTION_ARGS)
1221 {
1222 	JsonbInState result;
1223 
1224 	memset(&result, 0, sizeof(JsonbInState));
1225 
1226 	(void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1227 	result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1228 
1229 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1230 }
1231 
1232 /*
1233  * SQL function jsonb_build_array(variadic "any")
1234  */
1235 Datum
jsonb_build_array(PG_FUNCTION_ARGS)1236 jsonb_build_array(PG_FUNCTION_ARGS)
1237 {
1238 	int			nargs;
1239 	int			i;
1240 	JsonbInState result;
1241 	Datum	   *args;
1242 	bool	   *nulls;
1243 	Oid		   *types;
1244 
1245 	/* build argument values to build the array */
1246 	nargs = extract_variadic_args(fcinfo, 0, true, &args, &types, &nulls);
1247 
1248 	if (nargs < 0)
1249 		PG_RETURN_NULL();
1250 
1251 	memset(&result, 0, sizeof(JsonbInState));
1252 
1253 	result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1254 
1255 	for (i = 0; i < nargs; i++)
1256 		add_jsonb(args[i], nulls[i], &result, types[i], false);
1257 
1258 	result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1259 
1260 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1261 }
1262 
1263 /*
1264  * degenerate case of jsonb_build_array where it gets 0 arguments.
1265  */
1266 Datum
jsonb_build_array_noargs(PG_FUNCTION_ARGS)1267 jsonb_build_array_noargs(PG_FUNCTION_ARGS)
1268 {
1269 	JsonbInState result;
1270 
1271 	memset(&result, 0, sizeof(JsonbInState));
1272 
1273 	(void) pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
1274 	result.res = pushJsonbValue(&result.parseState, WJB_END_ARRAY, NULL);
1275 
1276 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1277 }
1278 
1279 
1280 /*
1281  * SQL function jsonb_object(text[])
1282  *
1283  * take a one or two dimensional array of text as name value pairs
1284  * for a jsonb object.
1285  *
1286  */
1287 Datum
jsonb_object(PG_FUNCTION_ARGS)1288 jsonb_object(PG_FUNCTION_ARGS)
1289 {
1290 	ArrayType  *in_array = PG_GETARG_ARRAYTYPE_P(0);
1291 	int			ndims = ARR_NDIM(in_array);
1292 	Datum	   *in_datums;
1293 	bool	   *in_nulls;
1294 	int			in_count,
1295 				count,
1296 				i;
1297 	JsonbInState result;
1298 
1299 	memset(&result, 0, sizeof(JsonbInState));
1300 
1301 	(void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1302 
1303 	switch (ndims)
1304 	{
1305 		case 0:
1306 			goto close_object;
1307 			break;
1308 
1309 		case 1:
1310 			if ((ARR_DIMS(in_array)[0]) % 2)
1311 				ereport(ERROR,
1312 						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1313 						 errmsg("array must have even number of elements")));
1314 			break;
1315 
1316 		case 2:
1317 			if ((ARR_DIMS(in_array)[1]) != 2)
1318 				ereport(ERROR,
1319 						(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1320 						 errmsg("array must have two columns")));
1321 			break;
1322 
1323 		default:
1324 			ereport(ERROR,
1325 					(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1326 					 errmsg("wrong number of array subscripts")));
1327 	}
1328 
1329 	deconstruct_array(in_array,
1330 					  TEXTOID, -1, false, 'i',
1331 					  &in_datums, &in_nulls, &in_count);
1332 
1333 	count = in_count / 2;
1334 
1335 	for (i = 0; i < count; ++i)
1336 	{
1337 		JsonbValue	v;
1338 		char	   *str;
1339 		int			len;
1340 
1341 		if (in_nulls[i * 2])
1342 			ereport(ERROR,
1343 					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1344 					 errmsg("null value not allowed for object key")));
1345 
1346 		str = TextDatumGetCString(in_datums[i * 2]);
1347 		len = strlen(str);
1348 
1349 		v.type = jbvString;
1350 
1351 		v.val.string.len = len;
1352 		v.val.string.val = str;
1353 
1354 		(void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1355 
1356 		if (in_nulls[i * 2 + 1])
1357 		{
1358 			v.type = jbvNull;
1359 		}
1360 		else
1361 		{
1362 			str = TextDatumGetCString(in_datums[i * 2 + 1]);
1363 			len = strlen(str);
1364 
1365 			v.type = jbvString;
1366 
1367 			v.val.string.len = len;
1368 			v.val.string.val = str;
1369 		}
1370 
1371 		(void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1372 	}
1373 
1374 	pfree(in_datums);
1375 	pfree(in_nulls);
1376 
1377 close_object:
1378 	result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1379 
1380 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1381 }
1382 
1383 /*
1384  * SQL function jsonb_object(text[], text[])
1385  *
1386  * take separate name and value arrays of text to construct a jsonb object
1387  * pairwise.
1388  */
1389 Datum
jsonb_object_two_arg(PG_FUNCTION_ARGS)1390 jsonb_object_two_arg(PG_FUNCTION_ARGS)
1391 {
1392 	ArrayType  *key_array = PG_GETARG_ARRAYTYPE_P(0);
1393 	ArrayType  *val_array = PG_GETARG_ARRAYTYPE_P(1);
1394 	int			nkdims = ARR_NDIM(key_array);
1395 	int			nvdims = ARR_NDIM(val_array);
1396 	Datum	   *key_datums,
1397 			   *val_datums;
1398 	bool	   *key_nulls,
1399 			   *val_nulls;
1400 	int			key_count,
1401 				val_count,
1402 				i;
1403 	JsonbInState result;
1404 
1405 	memset(&result, 0, sizeof(JsonbInState));
1406 
1407 	(void) pushJsonbValue(&result.parseState, WJB_BEGIN_OBJECT, NULL);
1408 
1409 	if (nkdims > 1 || nkdims != nvdims)
1410 		ereport(ERROR,
1411 				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1412 				 errmsg("wrong number of array subscripts")));
1413 
1414 	if (nkdims == 0)
1415 		goto close_object;
1416 
1417 	deconstruct_array(key_array,
1418 					  TEXTOID, -1, false, 'i',
1419 					  &key_datums, &key_nulls, &key_count);
1420 
1421 	deconstruct_array(val_array,
1422 					  TEXTOID, -1, false, 'i',
1423 					  &val_datums, &val_nulls, &val_count);
1424 
1425 	if (key_count != val_count)
1426 		ereport(ERROR,
1427 				(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
1428 				 errmsg("mismatched array dimensions")));
1429 
1430 	for (i = 0; i < key_count; ++i)
1431 	{
1432 		JsonbValue	v;
1433 		char	   *str;
1434 		int			len;
1435 
1436 		if (key_nulls[i])
1437 			ereport(ERROR,
1438 					(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
1439 					 errmsg("null value not allowed for object key")));
1440 
1441 		str = TextDatumGetCString(key_datums[i]);
1442 		len = strlen(str);
1443 
1444 		v.type = jbvString;
1445 
1446 		v.val.string.len = len;
1447 		v.val.string.val = str;
1448 
1449 		(void) pushJsonbValue(&result.parseState, WJB_KEY, &v);
1450 
1451 		if (val_nulls[i])
1452 		{
1453 			v.type = jbvNull;
1454 		}
1455 		else
1456 		{
1457 			str = TextDatumGetCString(val_datums[i]);
1458 			len = strlen(str);
1459 
1460 			v.type = jbvString;
1461 
1462 			v.val.string.len = len;
1463 			v.val.string.val = str;
1464 		}
1465 
1466 		(void) pushJsonbValue(&result.parseState, WJB_VALUE, &v);
1467 	}
1468 
1469 	pfree(key_datums);
1470 	pfree(key_nulls);
1471 	pfree(val_datums);
1472 	pfree(val_nulls);
1473 
1474 close_object:
1475 	result.res = pushJsonbValue(&result.parseState, WJB_END_OBJECT, NULL);
1476 
1477 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1478 }
1479 
1480 
1481 /*
1482  * shallow clone of a parse state, suitable for use in aggregate
1483  * final functions that will only append to the values rather than
1484  * change them.
1485  */
1486 static JsonbParseState *
clone_parse_state(JsonbParseState * state)1487 clone_parse_state(JsonbParseState *state)
1488 {
1489 	JsonbParseState *result,
1490 			   *icursor,
1491 			   *ocursor;
1492 
1493 	if (state == NULL)
1494 		return NULL;
1495 
1496 	result = palloc(sizeof(JsonbParseState));
1497 	icursor = state;
1498 	ocursor = result;
1499 	for (;;)
1500 	{
1501 		ocursor->contVal = icursor->contVal;
1502 		ocursor->size = icursor->size;
1503 		icursor = icursor->next;
1504 		if (icursor == NULL)
1505 			break;
1506 		ocursor->next = palloc(sizeof(JsonbParseState));
1507 		ocursor = ocursor->next;
1508 	}
1509 	ocursor->next = NULL;
1510 
1511 	return result;
1512 }
1513 
1514 
1515 /*
1516  * jsonb_agg aggregate function
1517  */
1518 Datum
jsonb_agg_transfn(PG_FUNCTION_ARGS)1519 jsonb_agg_transfn(PG_FUNCTION_ARGS)
1520 {
1521 	MemoryContext oldcontext,
1522 				aggcontext;
1523 	JsonbAggState *state;
1524 	JsonbInState elem;
1525 	Datum		val;
1526 	JsonbInState *result;
1527 	bool		single_scalar = false;
1528 	JsonbIterator *it;
1529 	Jsonb	   *jbelem;
1530 	JsonbValue	v;
1531 	JsonbIteratorToken type;
1532 
1533 	if (!AggCheckCallContext(fcinfo, &aggcontext))
1534 	{
1535 		/* cannot be called directly because of internal-type argument */
1536 		elog(ERROR, "jsonb_agg_transfn called in non-aggregate context");
1537 	}
1538 
1539 	/* set up the accumulator on the first go round */
1540 
1541 	if (PG_ARGISNULL(0))
1542 	{
1543 		Oid			arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1544 
1545 		if (arg_type == InvalidOid)
1546 			ereport(ERROR,
1547 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1548 					 errmsg("could not determine input data type")));
1549 
1550 		oldcontext = MemoryContextSwitchTo(aggcontext);
1551 		state = palloc(sizeof(JsonbAggState));
1552 		result = palloc0(sizeof(JsonbInState));
1553 		state->res = result;
1554 		result->res = pushJsonbValue(&result->parseState,
1555 									 WJB_BEGIN_ARRAY, NULL);
1556 		MemoryContextSwitchTo(oldcontext);
1557 
1558 		jsonb_categorize_type(arg_type, &state->val_category,
1559 							  &state->val_output_func);
1560 	}
1561 	else
1562 	{
1563 		state = (JsonbAggState *) PG_GETARG_POINTER(0);
1564 		result = state->res;
1565 	}
1566 
1567 	/* turn the argument into jsonb in the normal function context */
1568 
1569 	val = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1);
1570 
1571 	memset(&elem, 0, sizeof(JsonbInState));
1572 
1573 	datum_to_jsonb(val, PG_ARGISNULL(1), &elem, state->val_category,
1574 				   state->val_output_func, false);
1575 
1576 	jbelem = JsonbValueToJsonb(elem.res);
1577 
1578 	/* switch to the aggregate context for accumulation operations */
1579 
1580 	oldcontext = MemoryContextSwitchTo(aggcontext);
1581 
1582 	it = JsonbIteratorInit(&jbelem->root);
1583 
1584 	while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1585 	{
1586 		switch (type)
1587 		{
1588 			case WJB_BEGIN_ARRAY:
1589 				if (v.val.array.rawScalar)
1590 					single_scalar = true;
1591 				else
1592 					result->res = pushJsonbValue(&result->parseState,
1593 												 type, NULL);
1594 				break;
1595 			case WJB_END_ARRAY:
1596 				if (!single_scalar)
1597 					result->res = pushJsonbValue(&result->parseState,
1598 												 type, NULL);
1599 				break;
1600 			case WJB_BEGIN_OBJECT:
1601 			case WJB_END_OBJECT:
1602 				result->res = pushJsonbValue(&result->parseState,
1603 											 type, NULL);
1604 				break;
1605 			case WJB_ELEM:
1606 			case WJB_KEY:
1607 			case WJB_VALUE:
1608 				if (v.type == jbvString)
1609 				{
1610 					/* copy string values in the aggregate context */
1611 					char	   *buf = palloc(v.val.string.len + 1);
1612 
1613 					snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1614 					v.val.string.val = buf;
1615 				}
1616 				else if (v.type == jbvNumeric)
1617 				{
1618 					/* same for numeric */
1619 					v.val.numeric =
1620 					DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
1621 											NumericGetDatum(v.val.numeric)));
1622 				}
1623 				result->res = pushJsonbValue(&result->parseState,
1624 											 type, &v);
1625 				break;
1626 			default:
1627 				elog(ERROR, "unknown jsonb iterator token type");
1628 		}
1629 	}
1630 
1631 	MemoryContextSwitchTo(oldcontext);
1632 
1633 	PG_RETURN_POINTER(state);
1634 }
1635 
1636 Datum
jsonb_agg_finalfn(PG_FUNCTION_ARGS)1637 jsonb_agg_finalfn(PG_FUNCTION_ARGS)
1638 {
1639 	JsonbAggState *arg;
1640 	JsonbInState result;
1641 	Jsonb	   *out;
1642 
1643 	/* cannot be called directly because of internal-type argument */
1644 	Assert(AggCheckCallContext(fcinfo, NULL));
1645 
1646 	if (PG_ARGISNULL(0))
1647 		PG_RETURN_NULL();		/* returns null iff no input values */
1648 
1649 	arg = (JsonbAggState *) PG_GETARG_POINTER(0);
1650 
1651 	/*
1652 	 * We need to do a shallow clone of the argument in case the final
1653 	 * function is called more than once, so we avoid changing the argument. A
1654 	 * shallow clone is sufficient as we aren't going to change any of the
1655 	 * values, just add the final array end marker.
1656 	 */
1657 
1658 	result.parseState = clone_parse_state(arg->res->parseState);
1659 
1660 	result.res = pushJsonbValue(&result.parseState,
1661 								WJB_END_ARRAY, NULL);
1662 
1663 	out = JsonbValueToJsonb(result.res);
1664 
1665 	PG_RETURN_POINTER(out);
1666 }
1667 
1668 /*
1669  * jsonb_object_agg aggregate function
1670  */
1671 Datum
jsonb_object_agg_transfn(PG_FUNCTION_ARGS)1672 jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
1673 {
1674 	MemoryContext oldcontext,
1675 				aggcontext;
1676 	JsonbInState elem;
1677 	JsonbAggState *state;
1678 	Datum		val;
1679 	JsonbInState *result;
1680 	bool		single_scalar;
1681 	JsonbIterator *it;
1682 	Jsonb	   *jbkey,
1683 			   *jbval;
1684 	JsonbValue	v;
1685 	JsonbIteratorToken type;
1686 
1687 	if (!AggCheckCallContext(fcinfo, &aggcontext))
1688 	{
1689 		/* cannot be called directly because of internal-type argument */
1690 		elog(ERROR, "jsonb_object_agg_transfn called in non-aggregate context");
1691 	}
1692 
1693 	/* set up the accumulator on the first go round */
1694 
1695 	if (PG_ARGISNULL(0))
1696 	{
1697 		Oid			arg_type;
1698 
1699 		oldcontext = MemoryContextSwitchTo(aggcontext);
1700 		state = palloc(sizeof(JsonbAggState));
1701 		result = palloc0(sizeof(JsonbInState));
1702 		state->res = result;
1703 		result->res = pushJsonbValue(&result->parseState,
1704 									 WJB_BEGIN_OBJECT, NULL);
1705 		MemoryContextSwitchTo(oldcontext);
1706 
1707 		arg_type = get_fn_expr_argtype(fcinfo->flinfo, 1);
1708 
1709 		if (arg_type == InvalidOid)
1710 			ereport(ERROR,
1711 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1712 					 errmsg("could not determine input data type")));
1713 
1714 		jsonb_categorize_type(arg_type, &state->key_category,
1715 							  &state->key_output_func);
1716 
1717 		arg_type = get_fn_expr_argtype(fcinfo->flinfo, 2);
1718 
1719 		if (arg_type == InvalidOid)
1720 			ereport(ERROR,
1721 					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1722 					 errmsg("could not determine input data type")));
1723 
1724 		jsonb_categorize_type(arg_type, &state->val_category,
1725 							  &state->val_output_func);
1726 	}
1727 	else
1728 	{
1729 		state = (JsonbAggState *) PG_GETARG_POINTER(0);
1730 		result = state->res;
1731 	}
1732 
1733 	/* turn the argument into jsonb in the normal function context */
1734 
1735 	if (PG_ARGISNULL(1))
1736 		ereport(ERROR,
1737 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1738 				 errmsg("field name must not be null")));
1739 
1740 	val = PG_GETARG_DATUM(1);
1741 
1742 	memset(&elem, 0, sizeof(JsonbInState));
1743 
1744 	datum_to_jsonb(val, false, &elem, state->key_category,
1745 				   state->key_output_func, true);
1746 
1747 	jbkey = JsonbValueToJsonb(elem.res);
1748 
1749 	val = PG_ARGISNULL(2) ? (Datum) 0 : PG_GETARG_DATUM(2);
1750 
1751 	memset(&elem, 0, sizeof(JsonbInState));
1752 
1753 	datum_to_jsonb(val, PG_ARGISNULL(2), &elem, state->val_category,
1754 				   state->val_output_func, false);
1755 
1756 	jbval = JsonbValueToJsonb(elem.res);
1757 
1758 	it = JsonbIteratorInit(&jbkey->root);
1759 
1760 	/* switch to the aggregate context for accumulation operations */
1761 
1762 	oldcontext = MemoryContextSwitchTo(aggcontext);
1763 
1764 	/*
1765 	 * keys should be scalar, and we should have already checked for that
1766 	 * above when calling datum_to_jsonb, so we only need to look for these
1767 	 * things.
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 					elog(ERROR, "unexpected structure for key");
1777 				break;
1778 			case WJB_ELEM:
1779 				if (v.type == jbvString)
1780 				{
1781 					/* copy string values in the aggregate context */
1782 					char	   *buf = palloc(v.val.string.len + 1);
1783 
1784 					snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1785 					v.val.string.val = buf;
1786 				}
1787 				else
1788 				{
1789 					ereport(ERROR,
1790 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1791 							 errmsg("object keys must be strings")));
1792 				}
1793 				result->res = pushJsonbValue(&result->parseState,
1794 											 WJB_KEY, &v);
1795 				break;
1796 			case WJB_END_ARRAY:
1797 				break;
1798 			default:
1799 				elog(ERROR, "unexpected structure for key");
1800 				break;
1801 		}
1802 	}
1803 
1804 	it = JsonbIteratorInit(&jbval->root);
1805 
1806 	single_scalar = false;
1807 
1808 	/*
1809 	 * values can be anything, including structured and null, so we treat them
1810 	 * as in json_agg_transfn, except that single scalars are always pushed as
1811 	 * WJB_VALUE items.
1812 	 */
1813 
1814 	while ((type = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
1815 	{
1816 		switch (type)
1817 		{
1818 			case WJB_BEGIN_ARRAY:
1819 				if (v.val.array.rawScalar)
1820 					single_scalar = true;
1821 				else
1822 					result->res = pushJsonbValue(&result->parseState,
1823 												 type, NULL);
1824 				break;
1825 			case WJB_END_ARRAY:
1826 				if (!single_scalar)
1827 					result->res = pushJsonbValue(&result->parseState,
1828 												 type, NULL);
1829 				break;
1830 			case WJB_BEGIN_OBJECT:
1831 			case WJB_END_OBJECT:
1832 				result->res = pushJsonbValue(&result->parseState,
1833 											 type, NULL);
1834 				break;
1835 			case WJB_ELEM:
1836 			case WJB_KEY:
1837 			case WJB_VALUE:
1838 				if (v.type == jbvString)
1839 				{
1840 					/* copy string values in the aggregate context */
1841 					char	   *buf = palloc(v.val.string.len + 1);
1842 
1843 					snprintf(buf, v.val.string.len + 1, "%s", v.val.string.val);
1844 					v.val.string.val = buf;
1845 				}
1846 				else if (v.type == jbvNumeric)
1847 				{
1848 					/* same for numeric */
1849 					v.val.numeric =
1850 					DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
1851 											NumericGetDatum(v.val.numeric)));
1852 				}
1853 				result->res = pushJsonbValue(&result->parseState,
1854 											 single_scalar ? WJB_VALUE : type,
1855 											 &v);
1856 				break;
1857 			default:
1858 				elog(ERROR, "unknown jsonb iterator token type");
1859 		}
1860 	}
1861 
1862 	MemoryContextSwitchTo(oldcontext);
1863 
1864 	PG_RETURN_POINTER(state);
1865 }
1866 
1867 Datum
jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)1868 jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
1869 {
1870 	JsonbAggState *arg;
1871 	JsonbInState result;
1872 	Jsonb	   *out;
1873 
1874 	/* cannot be called directly because of internal-type argument */
1875 	Assert(AggCheckCallContext(fcinfo, NULL));
1876 
1877 	if (PG_ARGISNULL(0))
1878 		PG_RETURN_NULL();		/* returns null iff no input values */
1879 
1880 	arg = (JsonbAggState *) PG_GETARG_POINTER(0);
1881 
1882 	/*
1883 	 * We need to do a shallow clone of the argument's res field in case the
1884 	 * final function is called more than once, so we avoid changing the
1885 	 * aggregate state value.  A shallow clone is sufficient as we aren't
1886 	 * going to change any of the values, just add the final object end
1887 	 * marker.
1888 	 */
1889 
1890 	result.parseState = clone_parse_state(arg->res->parseState);
1891 
1892 	result.res = pushJsonbValue(&result.parseState,
1893 								WJB_END_OBJECT, NULL);
1894 
1895 	out = JsonbValueToJsonb(result.res);
1896 
1897 	PG_RETURN_POINTER(out);
1898 }
1899