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 {
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)) || 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
datum_to_jsonb(Datum val,bool is_null,JsonbInState * result,JsonbTypeCategory tcategory,Oid outfuncoid,bool key_scalar)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 
709 	check_stack_depth();
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 					{
800 						j2date(date + POSTGRES_EPOCH_JDATE,
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 				{
811 					Timestamp	timestamp;
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;
831 			case JSONBTYPE_TIMESTAMPTZ:
832 				{
833 					TimestampTz timestamp;
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 
869 					sem.object_start = jsonb_in_object_start;
870 					sem.array_start = jsonb_in_array_start;
871 					sem.object_end = jsonb_in_object_end;
872 					sem.array_end = jsonb_in_array_end;
873 					sem.scalar = jsonb_in_scalar;
874 					sem.object_field_start = jsonb_in_object_field_start;
875 
876 					pg_parse_json(lex, &sem);
877 
878 				}
879 				break;
880 			case JSONBTYPE_JSONB:
881 				{
882 					Jsonb	   *jsonb = DatumGetJsonb(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 					{
896 						JsonbIteratorToken type;
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
array_dim_to_jsonb(JsonbInState * result,int dim,int ndims,int * dims,Datum * vals,bool * nulls,int * valcount,JsonbTypeCategory tcategory,Oid outfuncoid)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
array_to_jsonb_internal(Datum array,JsonbInState * result)999 array_to_jsonb_internal(Datum array, JsonbInState *result)
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
composite_to_jsonb(Datum composite,JsonbInState * result)1047 composite_to_jsonb(Datum composite, JsonbInState *result)
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 
1080 		if (tupdesc->attrs[i]->attisdropped)
1081 			continue;
1082 
1083 		attname = NameStr(tupdesc->attrs[i]->attname);
1084 
1085 		v.type = jbvString;
1086 		/* don't need checkStringLen here - can't exceed maximum name length */
1087 		v.val.string.len = strlen(attname);
1088 		v.val.string.val = attname;
1089 
1090 		result->res = pushJsonbValue(&result->parseState, WJB_KEY, &v);
1091 
1092 		val = heap_getattr(tuple, i + 1, tupdesc, &isnull);
1093 
1094 		if (isnull)
1095 		{
1096 			tcategory = JSONBTYPE_NULL;
1097 			outfuncoid = InvalidOid;
1098 		}
1099 		else
1100 			jsonb_categorize_type(tupdesc->attrs[i]->atttypid,
1101 								  &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
add_jsonb(Datum val,bool is_null,JsonbInState * result,Oid val_type,bool key_scalar)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
to_jsonb(PG_FUNCTION_ARGS)1146 to_jsonb(PG_FUNCTION_ARGS)
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 
1166 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1167 }
1168 
1169 /*
1170  * SQL function jsonb_build_object(variadic "any")
1171  */
1172 Datum
jsonb_build_object(PG_FUNCTION_ARGS)1173 jsonb_build_object(PG_FUNCTION_ARGS)
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 
1214 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1215 }
1216 
1217 /*
1218  * degenerate case of jsonb_build_object where it gets 0 arguments.
1219  */
1220 Datum
jsonb_build_object_noargs(PG_FUNCTION_ARGS)1221 jsonb_build_object_noargs(PG_FUNCTION_ARGS)
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 
1230 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1231 }
1232 
1233 /*
1234  * SQL function jsonb_build_array(variadic "any")
1235  */
1236 Datum
jsonb_build_array(PG_FUNCTION_ARGS)1237 jsonb_build_array(PG_FUNCTION_ARGS)
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 
1261 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
1262 }
1263 
1264 /*
1265  * degenerate case of jsonb_build_array where it gets 0 arguments.
1266  */
1267 Datum
jsonb_build_array_noargs(PG_FUNCTION_ARGS)1268 jsonb_build_array_noargs(PG_FUNCTION_ARGS)
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 
1277 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
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
jsonb_object(PG_FUNCTION_ARGS)1289 jsonb_object(PG_FUNCTION_ARGS)
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 
1381 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
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
jsonb_object_two_arg(PG_FUNCTION_ARGS)1391 jsonb_object_two_arg(PG_FUNCTION_ARGS)
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 
1478 	PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
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 *
clone_parse_state(JsonbParseState * state)1488 clone_parse_state(JsonbParseState *state)
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
jsonb_agg_transfn(PG_FUNCTION_ARGS)1520 jsonb_agg_transfn(PG_FUNCTION_ARGS)
1521 {
1522 	MemoryContext oldcontext,
1523 				aggcontext;
1524 	JsonbAggState *state;
1525 	JsonbInState elem;
1526 	Datum		val;
1527 	JsonbInState *result;
1528 	bool		single_scalar = false;
1529 	JsonbIterator *it;
1530 	Jsonb	   *jbelem;
1531 	JsonbValue	v;
1532 	JsonbIteratorToken type;
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 =
1621 						DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
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
jsonb_agg_finalfn(PG_FUNCTION_ARGS)1638 jsonb_agg_finalfn(PG_FUNCTION_ARGS)
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
jsonb_object_agg_transfn(PG_FUNCTION_ARGS)1673 jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
1674 {
1675 	MemoryContext oldcontext,
1676 				aggcontext;
1677 	JsonbInState elem;
1678 	JsonbAggState *state;
1679 	Datum		val;
1680 	JsonbInState *result;
1681 	bool		single_scalar;
1682 	JsonbIterator *it;
1683 	Jsonb	   *jbkey,
1684 			   *jbval;
1685 	JsonbValue	v;
1686 	JsonbIteratorToken type;
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 =
1851 						DatumGetNumeric(DirectFunctionCall1(numeric_uplus,
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
jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)1869 jsonb_object_agg_finalfn(PG_FUNCTION_ARGS)
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 }
1900