@@ -3762,7 +3762,7 @@ checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
37623762 Oid targettype , bool allow_format_for_non_strings )
37633763{
37643764 if (!allow_format_for_non_strings &&
3765- format -> type != JS_FORMAT_DEFAULT &&
3765+ format -> format != JS_FORMAT_DEFAULT &&
37663766 (targettype != BYTEAOID &&
37673767 targettype != JSONOID &&
37683768 targettype != JSONBOID ))
@@ -3779,7 +3779,7 @@ checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
37793779 errmsg ("cannot use JSON format with non-string output types" )));
37803780 }
37813781
3782- if (format -> type == JS_FORMAT_JSON )
3782+ if (format -> format == JS_FORMAT_JSON )
37833783 {
37843784 JsonEncoding enc = format -> encoding != JS_ENC_DEFAULT ?
37853785 format -> encoding : JS_ENC_UTF8 ;
@@ -3807,23 +3807,25 @@ checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
38073807 * Assigns default format or checks specified format for its applicability to
38083808 * the target type.
38093809 */
3810- static void
3810+ static JsonReturning *
38113811transformJsonOutput (ParseState * pstate , const JsonOutput * output ,
3812- bool allow_format , JsonReturning * ret )
3812+ bool allow_format )
38133813{
3814+ JsonReturning * ret ;
3815+
38143816 /* if output clause is not specified, make default clause value */
38153817 if (!output )
38163818 {
3817- ret -> format . type = JS_FORMAT_DEFAULT ;
3818- ret -> format . encoding = JS_ENC_DEFAULT ;
3819- ret -> format . location = -1 ;
3819+ ret = makeNode ( JsonReturning ) ;
3820+
3821+ ret -> format = makeJsonFormat ( JS_FORMAT_DEFAULT , JS_ENC_DEFAULT , -1 ) ;
38203822 ret -> typid = InvalidOid ;
38213823 ret -> typmod = -1 ;
38223824
3823- return ;
3825+ return ret ;
38243826 }
38253827
3826- * ret = output -> returning ;
3828+ ret = copyObject ( output -> returning ) ;
38273829
38283830 typenameTypeIdAndMod (pstate , output -> typeName , & ret -> typid , & ret -> typmod );
38293831
@@ -3832,20 +3834,73 @@ transformJsonOutput(ParseState *pstate, const JsonOutput *output,
38323834 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
38333835 errmsg ("returning SETOF types is not supported in SQL/JSON functions" )));
38343836
3835- if (ret -> format . type == JS_FORMAT_DEFAULT )
3837+ if (ret -> format -> format == JS_FORMAT_DEFAULT )
38363838 /* assign JSONB format when returning jsonb, or JSON format otherwise */
3837- ret -> format . type =
3839+ ret -> format -> format =
38383840 ret -> typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON ;
38393841 else
3840- checkJsonOutputFormat (pstate , & ret -> format , ret -> typid , allow_format );
3842+ checkJsonOutputFormat (pstate , ret -> format , ret -> typid , allow_format );
3843+
3844+ return ret ;
3845+ }
3846+
3847+ /*
3848+ * Transform JSON output clause of JSON contructor functions.
3849+ *
3850+ * Derive RETURNING type, if not specified, from argument types.
3851+ */
3852+ static JsonReturning *
3853+ transformJsonCtorOutput (ParseState * pstate , JsonOutput * output , List * args )
3854+ {
3855+ JsonReturning * returning = transformJsonOutput (pstate , output , true);
3856+
3857+ if (!OidIsValid (returning -> typid ))
3858+ {
3859+ ListCell * lc ;
3860+ bool have_json = false;
3861+ bool have_jsonb = false;
3862+
3863+ foreach (lc , args )
3864+ {
3865+ Node * expr = lfirst (lc );
3866+ Oid typid = exprType (expr );
3867+
3868+ have_json |= typid == JSONOID ;
3869+ have_jsonb |= typid == JSONBOID ;
3870+
3871+ if (have_jsonb )
3872+ break ;
3873+ }
3874+
3875+ if (have_jsonb )
3876+ {
3877+ returning -> typid = JSONBOID ;
3878+ returning -> format -> format = JS_FORMAT_JSONB ;
3879+ }
3880+ else if (have_json )
3881+ {
3882+ returning -> typid = JSONOID ;
3883+ returning -> format -> format = JS_FORMAT_JSON ;
3884+ }
3885+ else
3886+ {
3887+ /* XXX TEXTOID is default by standard */
3888+ returning -> typid = JSONOID ;
3889+ returning -> format -> format = JS_FORMAT_JSON ;
3890+ }
3891+
3892+ returning -> typmod = -1 ;
3893+ }
3894+
3895+ return returning ;
38413896}
38423897
38433898/*
38443899 * Coerce json[b]-valued function expression to the output type.
38453900 */
38463901static Node *
3847- coerceJsonFuncExpr (ParseState * pstate , Node * expr , JsonReturning * returning ,
3848- bool report_error )
3902+ coerceJsonFuncExpr (ParseState * pstate , Node * expr ,
3903+ const JsonReturning * returning , bool report_error )
38493904{
38503905 Node * res ;
38513906 int location ;
@@ -3858,16 +3913,16 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr, JsonReturning *returning,
38583913 location = exprLocation (expr );
38593914
38603915 if (location < 0 )
3861- location = returning ? returning -> format . location : -1 ;
3916+ location = returning ? returning -> format -> location : -1 ;
38623917
38633918 /* special case for RETURNING bytea FORMAT json */
3864- if (returning -> format . type == JS_FORMAT_JSON &&
3919+ if (returning -> format -> format == JS_FORMAT_JSON &&
38653920 returning -> typid == BYTEAOID )
38663921 {
38673922 /* encode json text into bytea using pg_convert_to() */
38683923 Node * texpr = coerce_to_specific_type (pstate , expr , TEXTOID ,
38693924 "JSON_FUNCTION" );
3870- Const * enc = getJsonEncodingConst (& returning -> format );
3925+ Const * enc = getJsonEncodingConst (returning -> format );
38713926 FuncExpr * fexpr = makeFuncExpr (F_PG_CONVERT_TO , BYTEAOID ,
38723927 list_make2 (texpr , enc ),
38733928 InvalidOid , InvalidOid ,
@@ -3908,7 +3963,7 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr, JsonReturning *returning,
39083963static Node *
39093964transformJsonObjectCtor (ParseState * pstate , JsonObjectCtor * ctor )
39103965{
3911- JsonReturning returning ;
3966+ JsonReturning * returning ;
39123967 JsonCtorExpr * jsctor ;
39133968 FuncExpr * fexpr ;
39143969 List * args = NIL ;
@@ -3937,9 +3992,9 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
39373992 }
39383993 }
39393994
3940- transformJsonOutput (pstate , ctor -> output , true, & returning );
3995+ returning = transformJsonCtorOutput (pstate , ctor -> output , args );
39413996
3942- if (returning . format . type == JS_FORMAT_JSONB )
3997+ if (returning -> format -> format == JS_FORMAT_JSONB )
39433998 {
39443999 funcid = args ? F_JSONB_BUILD_OBJECT_EXT : F_JSONB_BUILD_OBJECT_NOARGS ;
39454000 funcrettype = JSONBOID ;
@@ -3961,5 +4016,5 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
39614016 jsctor -> unique = ctor -> unique ;
39624017 jsctor -> absent_on_null = ctor -> absent_on_null ;
39634018
3964- return coerceJsonFuncExpr (pstate , (Node * ) jsctor , & returning , true);
4019+ return coerceJsonFuncExpr (pstate , (Node * ) jsctor , returning , true);
39654020}
0 commit comments