@@ -4150,17 +4150,21 @@ ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
41504150 */
41514151static Datum
41524152ExecEvalJsonBehavior (ExprContext * econtext , JsonBehavior * behavior ,
4153- ExprState * default_estate , bool * is_null )
4153+ ExprState * default_estate , bool is_jsonb , bool * is_null )
41544154{
41554155 * is_null = false;
41564156
41574157 switch (behavior -> btype )
41584158 {
41594159 case JSON_BEHAVIOR_EMPTY_ARRAY :
4160- return JsonbPGetDatum (JsonbMakeEmptyArray ());
4160+ return is_jsonb
4161+ ? JsonbPGetDatum (JsonbMakeEmptyArray ())
4162+ : PointerGetDatum (cstring_to_text ("[]" ));
41614163
41624164 case JSON_BEHAVIOR_EMPTY_OBJECT :
4163- return JsonbPGetDatum (JsonbMakeEmptyObject ());
4165+ return is_jsonb
4166+ ? JsonbPGetDatum (JsonbMakeEmptyObject ())
4167+ : PointerGetDatum (cstring_to_text ("{}" ));
41644168
41654169 case JSON_BEHAVIOR_TRUE :
41664170 return BoolGetDatum (true);
@@ -4187,17 +4191,20 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
41874191 */
41884192static Datum
41894193ExecEvalJsonExprCoercion (ExprEvalStep * op , ExprContext * econtext ,
4190- Datum res , bool * isNull )
4194+ Datum res , bool * isNull , bool isJsonb )
41914195{
41924196 JsonExpr * jexpr = op -> d .jsonexpr .jsexpr ;
41934197 JsonCoercion * coercion = jexpr -> result_coercion ;
4194- Jsonb * jb = * isNull ? NULL : DatumGetJsonbP (res );
4198+ Jsonb * jb = * isNull || !isJsonb ? NULL : DatumGetJsonbP (res );
4199+ Json * js = * isNull || isJsonb ? NULL : DatumGetJsonP (res );
41954200
41964201 if ((coercion && coercion -> via_io ) ||
4197- (jexpr -> omit_quotes && !* isNull && JB_ROOT_IS_SCALAR (jb )))
4202+ (jexpr -> omit_quotes && !* isNull &&
4203+ (isJsonb ? JB_ROOT_IS_SCALAR (jb ) : JsonContainerIsScalar (& js -> root ))))
41984204 {
41994205 /* strip quotes and call typinput function */
4200- char * str = * isNull ? NULL : JsonbUnquote (jb );
4206+ char * str = * isNull ? NULL :
4207+ (isJsonb ? JsonbUnquote (jb ) : JsonUnquote (js ));
42014208
42024209 res = InputFunctionCall (& op -> d .jsonexpr .input .func , str ,
42034210 op -> d .jsonexpr .input .typioparam ,
@@ -4211,7 +4218,7 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
42114218 res = ExecEvalExpr (op -> d .jsonexpr .result_expr , econtext , isNull );
42124219 }
42134220 else if (coercion && coercion -> via_populate )
4214- res = json_populate_type (res , JSONBOID ,
4221+ res = json_populate_type (res , isJsonb ? JSONBOID : JSONOID ,
42154222 jexpr -> returning .typid ,
42164223 jexpr -> returning .typmod ,
42174224 & op -> d .jsonexpr .cache ,
@@ -4245,7 +4252,7 @@ EvalJsonPathVar(void *cxt, bool *isnull)
42454252 * corresponding SQL type and a pointer to the coercion state.
42464253 */
42474254Datum
4248- ExecPrepareJsonItemCoercion (JsonbValue * item ,
4255+ ExecPrepareJsonItemCoercion (JsonbValue * item , bool is_jsonb ,
42494256 JsonReturning * returning ,
42504257 struct JsonCoercionsState * coercions ,
42514258 struct JsonCoercionState * * pcoercion )
@@ -4254,8 +4261,14 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
42544261 Datum res ;
42554262 JsonbValue jbvbuf ;
42564263
4257- if (item -> type == jbvBinary && JsonContainerIsScalar (item -> val .binary .data ))
4258- item = JsonbExtractScalar (item -> val .binary .data , & jbvbuf );
4264+ if (item -> type == jbvBinary )
4265+ {
4266+ if (JsonContainerIsScalar (item -> val .binary .data ))
4267+ item = is_jsonb
4268+ ? JsonbExtractScalar (item -> val .binary .data , & jbvbuf )
4269+ : JsonExtractScalar ((JsonContainer * ) item -> val .binary .data ,
4270+ & jbvbuf );
4271+ }
42594272
42604273 /* get coercion state reference and datum of the corresponding SQL type */
42614274 switch (item -> type )
@@ -4312,7 +4325,18 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
43124325 case jbvObject :
43134326 case jbvBinary :
43144327 coercion = & coercions -> composite ;
4315- res = JsonbPGetDatum (JsonbValueToJsonb (item ));
4328+ if (is_jsonb )
4329+ {
4330+ Jsonb * jb = JsonbValueToJsonb (item );
4331+
4332+ res = JsonbPGetDatum (jb );
4333+ }
4334+ else
4335+ {
4336+ Json * js = JsonbValueToJson (item );
4337+
4338+ res = JsonPGetDatum (js );
4339+ }
43164340 break ;
43174341
43184342 default :
@@ -4327,7 +4351,8 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
43274351
43284352static Datum
43294353ExecEvalJsonExpr (ExprState * state , ExprEvalStep * op , ExprContext * econtext ,
4330- JsonExpr * jexpr , JsonPath * path , Datum item , bool * resnull )
4354+ JsonExpr * jexpr , JsonPath * path , Datum item , bool isjsonb ,
4355+ bool * resnull )
43314356{
43324357 bool empty = false;
43334358 Datum res = (Datum ) 0 ;
@@ -4343,7 +4368,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
43434368 if (isnull )
43444369 {
43454370 /* execute domain checks for NULLs */
4346- (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4371+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull ,
4372+ isjsonb );
43474373 * resnull = true;
43484374 return (Datum ) 0 ;
43494375 }
@@ -4352,15 +4378,15 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
43524378 switch (jexpr -> op )
43534379 {
43544380 case IS_JSON_QUERY :
4355- res = JsonbPathQuery ( item , path , jexpr -> wrapper , & empty ,
4356- op -> d .jsonexpr .args );
4381+ res = ( isjsonb ? JsonbPathQuery : JsonPathQuery )
4382+ ( item , path , jexpr -> wrapper , & empty , op -> d .jsonexpr .args );
43574383 * resnull = !DatumGetPointer (res );
43584384 break ;
43594385
43604386 case IS_JSON_VALUE :
43614387 {
4362- JsonbValue * jbv = JsonbPathValue ( item , path , & empty ,
4363- op -> d .jsonexpr .args );
4388+ JsonbValue * jbv = ( isjsonb ? JsonbPathValue : JsonPathValue )
4389+ ( item , path , & empty , op -> d .jsonexpr .args );
43644390 struct JsonCoercionState * jcstate ;
43654391
43664392 if (!jbv ) /* NULL or empty */
@@ -4375,12 +4401,14 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
43754401 jexpr -> returning .typid == JSONBOID )
43764402 {
43774403 /* Use result coercion from json[b] to the output type */
4378- res = JsonbPGetDatum (JsonbValueToJsonb (jbv ));
4404+ res = isjsonb
4405+ ? JsonbPGetDatum (JsonbValueToJsonb (jbv ))
4406+ : JsonPGetDatum (JsonbValueToJson (jbv ));
43794407 break ;
43804408 }
43814409
43824410 /* Use coercion from SQL/JSON item type to the output type */
4383- res = ExecPrepareJsonItemCoercion (jbv ,
4411+ res = ExecPrepareJsonItemCoercion (jbv , isjsonb ,
43844412 & op -> d .jsonexpr .jsexpr -> returning ,
43854413 & op -> d .jsonexpr .coercions ,
43864414 & jcstate );
@@ -4416,7 +4444,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
44164444
44174445 case IS_JSON_EXISTS :
44184446 * resnull = false;
4419- return BoolGetDatum (JsonbPathExists (item , path , op -> d .jsonexpr .args ));
4447+ return BoolGetDatum ((isjsonb ? JsonbPathExists : JsonPathExists )
4448+ (item , path , op -> d .jsonexpr .args ));
44204449
44214450 default :
44224451 elog (ERROR , "unrecognized SQL/JSON expression op %d" , jexpr -> op );
@@ -4432,14 +4461,15 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
44324461
44334462 /* execute ON EMPTY behavior */
44344463 res = ExecEvalJsonBehavior (econtext , & jexpr -> on_empty ,
4435- op -> d .jsonexpr .default_on_empty , resnull );
4464+ op -> d .jsonexpr .default_on_empty ,
4465+ isjsonb , resnull );
44364466
44374467 /* result is already coerced in DEFAULT behavior case */
44384468 if (jexpr -> on_empty .btype == JSON_BEHAVIOR_DEFAULT )
44394469 return res ;
44404470 }
44414471
4442- return ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4472+ return ExecEvalJsonExprCoercion (op , econtext , res , resnull , isjsonb );
44434473}
44444474
44454475bool
@@ -4460,14 +4490,18 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
44604490 Datum res = (Datum ) 0 ;
44614491 JsonPath * path ;
44624492 ListCell * lc ;
4493+ Oid formattedType = exprType (jexpr -> formatted_expr ?
4494+ jexpr -> formatted_expr :
4495+ jexpr -> raw_expr );
4496+ bool isjsonb = formattedType == JSONBOID ;
44634497
44644498 * op -> resnull = true; /* until we get a result */
44654499 * op -> resvalue = (Datum ) 0 ;
44664500
44674501 if (op -> d .jsonexpr .raw_expr -> isnull || op -> d .jsonexpr .pathspec -> isnull )
44684502 {
44694503 /* execute domain checks for NULLs */
4470- (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull );
4504+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull , isjsonb );
44714505
44724506 Assert (* op -> resnull );
44734507 * op -> resnull = true;
@@ -4490,7 +4524,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
44904524 if (!ExecEvalJsonNeedsSubTransaction (jexpr ))
44914525 {
44924526 /* No need to use PG_TRY/PG_CATCH with subtransactions. */
4493- res = ExecEvalJsonExpr (state , op , econtext , jexpr , path , item ,
4527+ res = ExecEvalJsonExpr (state , op , econtext , jexpr , path , item , isjsonb ,
44944528 op -> resnull );
44954529 }
44964530 else
@@ -4509,7 +4543,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
45094543 PG_TRY ();
45104544 {
45114545 res = ExecEvalJsonExpr (state , op , econtext , jexpr , path , item ,
4512- op -> resnull );
4546+ isjsonb , op -> resnull );
45134547
45144548 /* Commit the inner transaction, return to outer xact context */
45154549 ReleaseCurrentSubTransaction ();
@@ -4536,12 +4570,13 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
45364570 /* Execute ON ERROR behavior. */
45374571 res = ExecEvalJsonBehavior (econtext , & jexpr -> on_error ,
45384572 op -> d .jsonexpr .default_on_error ,
4539- op -> resnull );
4573+ isjsonb , op -> resnull );
45404574
45414575 if (jexpr -> op != IS_JSON_EXISTS &&
45424576 /* result is already coerced in DEFAULT behavior case */
45434577 jexpr -> on_error .btype != JSON_BEHAVIOR_DEFAULT )
4544- res = ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull );
4578+ res = ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull ,
4579+ isjsonb );
45454580 }
45464581 PG_END_TRY ();
45474582 }
0 commit comments