@@ -4146,17 +4146,21 @@ ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
41464146 */
41474147static Datum
41484148ExecEvalJsonBehavior (ExprContext * econtext , JsonBehavior * behavior ,
4149- ExprState * default_estate , bool * is_null )
4149+ ExprState * default_estate , bool is_jsonb , bool * is_null )
41504150{
41514151 * is_null = false;
41524152
41534153 switch (behavior -> btype )
41544154 {
41554155 case JSON_BEHAVIOR_EMPTY_ARRAY :
4156- return JsonbPGetDatum (JsonbMakeEmptyArray ());
4156+ return is_jsonb
4157+ ? JsonbPGetDatum (JsonbMakeEmptyArray ())
4158+ : PointerGetDatum (cstring_to_text ("[]" ));
41574159
41584160 case JSON_BEHAVIOR_EMPTY_OBJECT :
4159- return JsonbPGetDatum (JsonbMakeEmptyObject ());
4161+ return is_jsonb
4162+ ? JsonbPGetDatum (JsonbMakeEmptyObject ())
4163+ : PointerGetDatum (cstring_to_text ("{}" ));
41604164
41614165 case JSON_BEHAVIOR_TRUE :
41624166 return BoolGetDatum (true);
@@ -4183,17 +4187,20 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
41834187 */
41844188static Datum
41854189ExecEvalJsonExprCoercion (ExprEvalStep * op , ExprContext * econtext ,
4186- Datum res , bool * isNull )
4190+ Datum res , bool * isNull , bool isJsonb )
41874191{
41884192 JsonExpr * jexpr = op -> d .jsonexpr .jsexpr ;
41894193 JsonCoercion * coercion = jexpr -> result_coercion ;
4190- Jsonb * jb = * isNull ? NULL : DatumGetJsonbP (res );
4194+ Jsonb * jb = * isNull || !isJsonb ? NULL : DatumGetJsonbP (res );
4195+ Json * js = * isNull || isJsonb ? NULL : DatumGetJsonP (res );
41914196
41924197 if ((coercion && coercion -> via_io ) ||
4193- (jexpr -> omit_quotes && !* isNull && JB_ROOT_IS_SCALAR (jb )))
4198+ (jexpr -> omit_quotes && !* isNull &&
4199+ (isJsonb ? JB_ROOT_IS_SCALAR (jb ) : JsonContainerIsScalar (& js -> root ))))
41944200 {
41954201 /* strip quotes and call typinput function */
4196- char * str = * isNull ? NULL : JsonbUnquote (jb );
4202+ char * str = * isNull ? NULL :
4203+ (isJsonb ? JsonbUnquote (jb ) : JsonUnquote (js ));
41974204
41984205 res = InputFunctionCall (& op -> d .jsonexpr .input .func , str ,
41994206 op -> d .jsonexpr .input .typioparam ,
@@ -4207,7 +4214,7 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
42074214 res = ExecEvalExpr (op -> d .jsonexpr .result_expr , econtext , isNull );
42084215 }
42094216 else if (coercion && coercion -> via_populate )
4210- res = json_populate_type (res , JSONBOID ,
4217+ res = json_populate_type (res , isJsonb ? JSONBOID : JSONOID ,
42114218 jexpr -> returning .typid ,
42124219 jexpr -> returning .typmod ,
42134220 & op -> d .jsonexpr .cache ,
@@ -4241,7 +4248,7 @@ EvalJsonPathVar(void *cxt, bool *isnull)
42414248 * corresponding SQL type and a pointer to the coercion state.
42424249 */
42434250Datum
4244- ExecPrepareJsonItemCoercion (JsonbValue * item ,
4251+ ExecPrepareJsonItemCoercion (JsonbValue * item , bool is_jsonb ,
42454252 JsonReturning * returning ,
42464253 struct JsonCoercionsState * coercions ,
42474254 struct JsonCoercionState * * pcoercion )
@@ -4250,8 +4257,14 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
42504257 Datum res ;
42514258 JsonbValue jbvbuf ;
42524259
4253- if (item -> type == jbvBinary && JsonContainerIsScalar (item -> val .binary .data ))
4254- item = JsonbExtractScalar (item -> val .binary .data , & jbvbuf );
4260+ if (item -> type == jbvBinary )
4261+ {
4262+ if (JsonContainerIsScalar (item -> val .binary .data ))
4263+ item = is_jsonb
4264+ ? JsonbExtractScalar (item -> val .binary .data , & jbvbuf )
4265+ : JsonExtractScalar ((JsonContainer * ) item -> val .binary .data ,
4266+ & jbvbuf );
4267+ }
42554268
42564269 /* get coercion state reference and datum of the corresponding SQL type */
42574270 switch (item -> type )
@@ -4308,7 +4321,18 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
43084321 case jbvObject :
43094322 case jbvBinary :
43104323 coercion = & coercions -> composite ;
4311- res = JsonbPGetDatum (JsonbValueToJsonb (item ));
4324+ if (is_jsonb )
4325+ {
4326+ Jsonb * jb = JsonbValueToJsonb (item );
4327+
4328+ res = JsonbPGetDatum (jb );
4329+ }
4330+ else
4331+ {
4332+ Json * js = JsonbValueToJson (item );
4333+
4334+ res = JsonPGetDatum (js );
4335+ }
43124336 break ;
43134337
43144338 default :
@@ -4323,7 +4347,8 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
43234347
43244348static Datum
43254349ExecEvalJsonExpr (ExprState * state , ExprEvalStep * op , ExprContext * econtext ,
4326- JsonExpr * jexpr , JsonPath * path , Datum item , bool * resnull )
4350+ JsonExpr * jexpr , JsonPath * path , Datum item , bool isjsonb ,
4351+ bool * resnull )
43274352{
43284353 bool empty = false;
43294354 Datum res = (Datum ) 0 ;
@@ -4339,7 +4364,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
43394364 if (isnull )
43404365 {
43414366 /* execute domain checks for NULLs */
4342- (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4367+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull ,
4368+ isjsonb );
43434369 * resnull = true;
43444370 return (Datum ) 0 ;
43454371 }
@@ -4348,23 +4374,23 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
43484374 switch (jexpr -> op )
43494375 {
43504376 case IS_JSON_QUERY :
4351- res = JsonbPathQuery ( item , path , jexpr -> wrapper , & empty ,
4352- op -> d .jsonexpr .args );
4377+ res = ( isjsonb ? JsonbPathQuery : JsonPathQuery )
4378+ ( item , path , jexpr -> wrapper , & empty , op -> d .jsonexpr .args );
43534379 * resnull = !DatumGetPointer (res );
43544380 break ;
43554381
43564382 case IS_JSON_VALUE :
43574383 {
4358- JsonbValue * jbv = JsonbPathValue ( item , path , & empty ,
4359- op -> d .jsonexpr .args );
4384+ JsonbValue * jbv = ( isjsonb ? JsonbPathValue : JsonPathValue )
4385+ ( item , path , & empty , op -> d .jsonexpr .args );
43604386 struct JsonCoercionState * jcstate ;
43614387
43624388 if (!jbv )
43634389 break ;
43644390
43654391 * resnull = false;
43664392
4367- res = ExecPrepareJsonItemCoercion (jbv ,
4393+ res = ExecPrepareJsonItemCoercion (jbv , isjsonb ,
43684394 & op -> d .jsonexpr .jsexpr -> returning ,
43694395 & op -> d .jsonexpr .coercions ,
43704396 & jcstate );
@@ -4377,8 +4403,11 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
43774403 jexpr -> returning .typid == JSONBOID )
43784404 {
43794405 /* use coercion via I/O from json[b] to the output type */
4380- res = JsonbPGetDatum (JsonbValueToJsonb (jbv ));
4381- res = ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4406+ res = isjsonb
4407+ ? JsonbPGetDatum (JsonbValueToJsonb (jbv ))
4408+ : JsonPGetDatum (JsonbValueToJson (jbv ));
4409+ res = ExecEvalJsonExprCoercion (op , econtext , res ,
4410+ resnull , isjsonb );
43824411 }
43834412 else if (jcstate -> estate )
43844413 {
@@ -4392,7 +4421,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
43924421 break ;
43934422
43944423 case IS_JSON_EXISTS :
4395- res = BoolGetDatum (JsonbPathExists (item , path , op -> d .jsonexpr .args ));
4424+ res = BoolGetDatum ((isjsonb ? JsonbPathExists : JsonPathExists )
4425+ (item , path , op -> d .jsonexpr .args ));
43964426 * resnull = false;
43974427 break ;
43984428
@@ -4411,14 +4441,15 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
44114441
44124442 /* execute ON EMPTY behavior */
44134443 res = ExecEvalJsonBehavior (econtext , & jexpr -> on_empty ,
4414- op -> d .jsonexpr .default_on_empty , resnull );
4444+ op -> d .jsonexpr .default_on_empty ,
4445+ isjsonb , resnull );
44154446 }
44164447
44174448 if (jexpr -> op != IS_JSON_EXISTS &&
44184449 (!empty ? jexpr -> op != IS_JSON_VALUE :
44194450 /* result is already coerced in DEFAULT behavior case */
44204451 jexpr -> on_empty .btype != JSON_BEHAVIOR_DEFAULT ))
4421- res = ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4452+ res = ExecEvalJsonExprCoercion (op , econtext , res , resnull , isjsonb );
44224453
44234454 return res ;
44244455}
@@ -4441,14 +4472,18 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
44414472 Datum res = (Datum ) 0 ;
44424473 JsonPath * path ;
44434474 ListCell * lc ;
4475+ Oid formattedType = exprType (jexpr -> formatted_expr ?
4476+ jexpr -> formatted_expr :
4477+ jexpr -> raw_expr );
4478+ bool isjsonb = formattedType == JSONBOID ;
44444479
44454480 * op -> resnull = true; /* until we get a result */
44464481 * op -> resvalue = (Datum ) 0 ;
44474482
44484483 if (op -> d .jsonexpr .raw_expr -> isnull || op -> d .jsonexpr .pathspec -> isnull )
44494484 {
44504485 /* execute domain checks for NULLs */
4451- (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull );
4486+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull , isjsonb );
44524487
44534488 Assert (* op -> resnull );
44544489 * op -> resnull = true;
@@ -4471,7 +4506,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
44714506 if (!ExecEvalJsonNeedsSubTransaction (jexpr ))
44724507 {
44734508 /* No need to use PG_TRY/PG_CATCH with subtransactions. */
4474- res = ExecEvalJsonExpr (state , op , econtext , jexpr , path , item ,
4509+ res = ExecEvalJsonExpr (state , op , econtext , jexpr , path , item , isjsonb ,
44754510 op -> resnull );
44764511 }
44774512 else
@@ -4498,7 +4533,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
44984533 PG_TRY ();
44994534 {
45004535 res = ExecEvalJsonExpr (state , op , newecontext , jexpr , path , item ,
4501- op -> resnull );
4536+ isjsonb , op -> resnull );
45024537
45034538 /* Commit the inner transaction, return to outer xact context */
45044539 ReleaseCurrentSubTransaction ();
@@ -4527,12 +4562,13 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
45274562 /* Execute ON ERROR behavior. */
45284563 res = ExecEvalJsonBehavior (econtext , & jexpr -> on_error ,
45294564 op -> d .jsonexpr .default_on_error ,
4530- op -> resnull );
4565+ isjsonb , op -> resnull );
45314566
45324567 if (jexpr -> op != IS_JSON_EXISTS &&
45334568 /* result is already coerced in DEFAULT behavior case */
45344569 jexpr -> on_error .btype != JSON_BEHAVIOR_DEFAULT )
4535- res = ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull );
4570+ res = ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull ,
4571+ isjsonb );
45364572 }
45374573 PG_END_TRY ();
45384574 }
0 commit comments