1919#include "funcapi.h"
2020#include "libpq/pqformat.h"
2121#include "miscadmin.h"
22- #include "parser/parse_coerce.h"
2322#include "utils/array.h"
2423#include "utils/builtins.h"
2524#include "utils/date.h"
2928#include "utils/lsyscache.h"
3029#include "utils/typcache.h"
3130
32- typedef enum /* type categories for datum_to_json */
33- {
34- JSONTYPE_NULL , /* null, so we didn't bother to identify */
35- JSONTYPE_BOOL , /* boolean (built-in types only) */
36- JSONTYPE_NUMERIC , /* numeric (ditto) */
37- JSONTYPE_DATE , /* we use special formatting for datetimes */
38- JSONTYPE_TIMESTAMP ,
39- JSONTYPE_TIMESTAMPTZ ,
40- JSONTYPE_JSON , /* JSON itself (and JSONB) */
41- JSONTYPE_ARRAY , /* array */
42- JSONTYPE_COMPOSITE , /* composite */
43- JSONTYPE_CAST , /* something with an explicit cast to JSON */
44- JSONTYPE_OTHER /* all else */
45- } JsonTypeCategory ;
46-
4731
4832/*
4933 * Support for fast key uniqueness checking.
@@ -107,9 +91,6 @@ static void array_dim_to_json(StringInfo result, int dim, int ndims, int *dims,
10791 bool use_line_feeds );
10892static void array_to_json_internal (Datum array , StringInfo result ,
10993 bool use_line_feeds );
110- static void json_categorize_type (Oid typoid ,
111- JsonTypeCategory * tcategory ,
112- Oid * outfuncoid );
11394static void datum_to_json (Datum val , bool is_null , StringInfo result ,
11495 JsonTypeCategory tcategory , Oid outfuncoid ,
11596 bool key_scalar );
@@ -182,106 +163,6 @@ json_recv(PG_FUNCTION_ARGS)
182163 PG_RETURN_TEXT_P (cstring_to_text_with_len (str , nbytes ));
183164}
184165
185- /*
186- * Determine how we want to print values of a given type in datum_to_json.
187- *
188- * Given the datatype OID, return its JsonTypeCategory, as well as the type's
189- * output function OID. If the returned category is JSONTYPE_CAST, we
190- * return the OID of the type->JSON cast function instead.
191- */
192- static void
193- json_categorize_type (Oid typoid ,
194- JsonTypeCategory * tcategory ,
195- Oid * outfuncoid )
196- {
197- bool typisvarlena ;
198-
199- /* Look through any domain */
200- typoid = getBaseType (typoid );
201-
202- * outfuncoid = InvalidOid ;
203-
204- /*
205- * We need to get the output function for everything except date and
206- * timestamp types, array and composite types, booleans, and non-builtin
207- * types where there's a cast to json.
208- */
209-
210- switch (typoid )
211- {
212- case BOOLOID :
213- * tcategory = JSONTYPE_BOOL ;
214- break ;
215-
216- case INT2OID :
217- case INT4OID :
218- case INT8OID :
219- case FLOAT4OID :
220- case FLOAT8OID :
221- case NUMERICOID :
222- getTypeOutputInfo (typoid , outfuncoid , & typisvarlena );
223- * tcategory = JSONTYPE_NUMERIC ;
224- break ;
225-
226- case DATEOID :
227- * tcategory = JSONTYPE_DATE ;
228- break ;
229-
230- case TIMESTAMPOID :
231- * tcategory = JSONTYPE_TIMESTAMP ;
232- break ;
233-
234- case TIMESTAMPTZOID :
235- * tcategory = JSONTYPE_TIMESTAMPTZ ;
236- break ;
237-
238- case JSONOID :
239- case JSONBOID :
240- getTypeOutputInfo (typoid , outfuncoid , & typisvarlena );
241- * tcategory = JSONTYPE_JSON ;
242- break ;
243-
244- default :
245- /* Check for arrays and composites */
246- if (OidIsValid (get_element_type (typoid )) || typoid == ANYARRAYOID
247- || typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID )
248- * tcategory = JSONTYPE_ARRAY ;
249- else if (type_is_rowtype (typoid )) /* includes RECORDOID */
250- * tcategory = JSONTYPE_COMPOSITE ;
251- else
252- {
253- /* It's probably the general case ... */
254- * tcategory = JSONTYPE_OTHER ;
255- /* but let's look for a cast to json, if it's not built-in */
256- if (typoid >= FirstNormalObjectId )
257- {
258- Oid castfunc ;
259- CoercionPathType ctype ;
260-
261- ctype = find_coercion_pathway (JSONOID , typoid ,
262- COERCION_EXPLICIT ,
263- & castfunc );
264- if (ctype == COERCION_PATH_FUNC && OidIsValid (castfunc ))
265- {
266- * tcategory = JSONTYPE_CAST ;
267- * outfuncoid = castfunc ;
268- }
269- else
270- {
271- /* non builtin type with no cast */
272- getTypeOutputInfo (typoid , outfuncoid , & typisvarlena );
273- }
274- }
275- else
276- {
277- /* any other builtin type */
278- getTypeOutputInfo (typoid , outfuncoid , & typisvarlena );
279- }
280- }
281- break ;
282- }
283- }
284-
285166/*
286167 * Turn a Datum into JSON text, appending the string to "result".
287168 *
@@ -591,7 +472,7 @@ array_to_json_internal(Datum array, StringInfo result, bool use_line_feeds)
591472 get_typlenbyvalalign (element_type ,
592473 & typlen , & typbyval , & typalign );
593474
594- json_categorize_type (element_type ,
475+ json_categorize_type (element_type , false,
595476 & tcategory , & outfuncoid );
596477
597478 deconstruct_array (v , element_type , typlen , typbyval ,
@@ -665,7 +546,8 @@ composite_to_json(Datum composite, StringInfo result, bool use_line_feeds)
665546 outfuncoid = InvalidOid ;
666547 }
667548 else
668- json_categorize_type (att -> atttypid , & tcategory , & outfuncoid );
549+ json_categorize_type (att -> atttypid , false, & tcategory ,
550+ & outfuncoid );
669551
670552 datum_to_json (val , isnull , result , tcategory , outfuncoid , false);
671553 }
@@ -699,7 +581,7 @@ add_json(Datum val, bool is_null, StringInfo result,
699581 outfuncoid = InvalidOid ;
700582 }
701583 else
702- json_categorize_type (val_type ,
584+ json_categorize_type (val_type , false,
703585 & tcategory , & outfuncoid );
704586
705587 datum_to_json (val , is_null , result , tcategory , outfuncoid , key_scalar );
@@ -784,12 +666,13 @@ to_json_is_immutable(Oid typoid)
784666 JsonTypeCategory tcategory ;
785667 Oid outfuncoid ;
786668
787- json_categorize_type (typoid , & tcategory , & outfuncoid );
669+ json_categorize_type (typoid , false, & tcategory , & outfuncoid );
788670
789671 switch (tcategory )
790672 {
791673 case JSONTYPE_BOOL :
792674 case JSONTYPE_JSON :
675+ case JSONTYPE_JSONB :
793676 case JSONTYPE_NULL :
794677 return true;
795678
@@ -830,7 +713,7 @@ to_json(PG_FUNCTION_ARGS)
830713 (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
831714 errmsg ("could not determine input data type" )));
832715
833- json_categorize_type (val_type ,
716+ json_categorize_type (val_type , false,
834717 & tcategory , & outfuncoid );
835718
836719 result = makeStringInfo ();
@@ -880,7 +763,7 @@ json_agg_transfn_worker(FunctionCallInfo fcinfo, bool absent_on_null)
880763 MemoryContextSwitchTo (oldcontext );
881764
882765 appendStringInfoChar (state -> str , '[' );
883- json_categorize_type (arg_type , & state -> val_category ,
766+ json_categorize_type (arg_type , false, & state -> val_category ,
884767 & state -> val_output_func );
885768 }
886769 else
@@ -1112,7 +995,7 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
1112995 (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1113996 errmsg ("could not determine data type for argument %d" , 1 )));
1114997
1115- json_categorize_type (arg_type , & state -> key_category ,
998+ json_categorize_type (arg_type , false, & state -> key_category ,
1116999 & state -> key_output_func );
11171000
11181001 arg_type = get_fn_expr_argtype (fcinfo -> flinfo , 2 );
@@ -1122,7 +1005,7 @@ json_object_agg_transfn_worker(FunctionCallInfo fcinfo,
11221005 (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
11231006 errmsg ("could not determine data type for argument %d" , 2 )));
11241007
1125- json_categorize_type (arg_type , & state -> val_category ,
1008+ json_categorize_type (arg_type , false, & state -> val_category ,
11261009 & state -> val_output_func );
11271010
11281011 appendStringInfoString (state -> str , "{ " );
0 commit comments