@@ -3762,7 +3762,7 @@ checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
3762
3762
Oid targettype , bool allow_format_for_non_strings )
3763
3763
{
3764
3764
if (!allow_format_for_non_strings &&
3765
- format -> type != JS_FORMAT_DEFAULT &&
3765
+ format -> format != JS_FORMAT_DEFAULT &&
3766
3766
(targettype != BYTEAOID &&
3767
3767
targettype != JSONOID &&
3768
3768
targettype != JSONBOID ))
@@ -3779,7 +3779,7 @@ checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
3779
3779
errmsg ("cannot use JSON format with non-string output types" )));
3780
3780
}
3781
3781
3782
- if (format -> type == JS_FORMAT_JSON )
3782
+ if (format -> format == JS_FORMAT_JSON )
3783
3783
{
3784
3784
JsonEncoding enc = format -> encoding != JS_ENC_DEFAULT ?
3785
3785
format -> encoding : JS_ENC_UTF8 ;
@@ -3807,23 +3807,25 @@ checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
3807
3807
* Assigns default format or checks specified format for its applicability to
3808
3808
* the target type.
3809
3809
*/
3810
- static void
3810
+ static JsonReturning *
3811
3811
transformJsonOutput (ParseState * pstate , const JsonOutput * output ,
3812
- bool allow_format , JsonReturning * ret )
3812
+ bool allow_format )
3813
3813
{
3814
+ JsonReturning * ret ;
3815
+
3814
3816
/* if output clause is not specified, make default clause value */
3815
3817
if (!output )
3816
3818
{
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 ) ;
3820
3822
ret -> typid = InvalidOid ;
3821
3823
ret -> typmod = -1 ;
3822
3824
3823
- return ;
3825
+ return ret ;
3824
3826
}
3825
3827
3826
- * ret = output -> returning ;
3828
+ ret = copyObject ( output -> returning ) ;
3827
3829
3828
3830
typenameTypeIdAndMod (pstate , output -> typeName , & ret -> typid , & ret -> typmod );
3829
3831
@@ -3832,20 +3834,73 @@ transformJsonOutput(ParseState *pstate, const JsonOutput *output,
3832
3834
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
3833
3835
errmsg ("returning SETOF types is not supported in SQL/JSON functions" )));
3834
3836
3835
- if (ret -> format . type == JS_FORMAT_DEFAULT )
3837
+ if (ret -> format -> format == JS_FORMAT_DEFAULT )
3836
3838
/* assign JSONB format when returning jsonb, or JSON format otherwise */
3837
- ret -> format . type =
3839
+ ret -> format -> format =
3838
3840
ret -> typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON ;
3839
3841
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 ;
3841
3896
}
3842
3897
3843
3898
/*
3844
3899
* Coerce json[b]-valued function expression to the output type.
3845
3900
*/
3846
3901
static 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 )
3849
3904
{
3850
3905
Node * res ;
3851
3906
int location ;
@@ -3858,16 +3913,16 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr, JsonReturning *returning,
3858
3913
location = exprLocation (expr );
3859
3914
3860
3915
if (location < 0 )
3861
- location = returning ? returning -> format . location : -1 ;
3916
+ location = returning ? returning -> format -> location : -1 ;
3862
3917
3863
3918
/* special case for RETURNING bytea FORMAT json */
3864
- if (returning -> format . type == JS_FORMAT_JSON &&
3919
+ if (returning -> format -> format == JS_FORMAT_JSON &&
3865
3920
returning -> typid == BYTEAOID )
3866
3921
{
3867
3922
/* encode json text into bytea using pg_convert_to() */
3868
3923
Node * texpr = coerce_to_specific_type (pstate , expr , TEXTOID ,
3869
3924
"JSON_FUNCTION" );
3870
- Const * enc = getJsonEncodingConst (& returning -> format );
3925
+ Const * enc = getJsonEncodingConst (returning -> format );
3871
3926
FuncExpr * fexpr = makeFuncExpr (F_PG_CONVERT_TO , BYTEAOID ,
3872
3927
list_make2 (texpr , enc ),
3873
3928
InvalidOid , InvalidOid ,
@@ -3908,7 +3963,7 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr, JsonReturning *returning,
3908
3963
static Node *
3909
3964
transformJsonObjectCtor (ParseState * pstate , JsonObjectCtor * ctor )
3910
3965
{
3911
- JsonReturning returning ;
3966
+ JsonReturning * returning ;
3912
3967
JsonCtorExpr * jsctor ;
3913
3968
FuncExpr * fexpr ;
3914
3969
List * args = NIL ;
@@ -3937,9 +3992,9 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
3937
3992
}
3938
3993
}
3939
3994
3940
- transformJsonOutput (pstate , ctor -> output , true, & returning );
3995
+ returning = transformJsonCtorOutput (pstate , ctor -> output , args );
3941
3996
3942
- if (returning . format . type == JS_FORMAT_JSONB )
3997
+ if (returning -> format -> format == JS_FORMAT_JSONB )
3943
3998
{
3944
3999
funcid = args ? F_JSONB_BUILD_OBJECT_EXT : F_JSONB_BUILD_OBJECT_NOARGS ;
3945
4000
funcrettype = JSONBOID ;
@@ -3961,5 +4016,5 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
3961
4016
jsctor -> unique = ctor -> unique ;
3962
4017
jsctor -> absent_on_null = ctor -> absent_on_null ;
3963
4018
3964
- return coerceJsonFuncExpr (pstate , (Node * ) jsctor , & returning , true);
4019
+ return coerceJsonFuncExpr (pstate , (Node * ) jsctor , returning , true);
3965
4020
}
0 commit comments