@@ -4146,17 +4146,21 @@ ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
4146
4146
*/
4147
4147
static Datum
4148
4148
ExecEvalJsonBehavior (ExprContext * econtext , JsonBehavior * behavior ,
4149
- ExprState * default_estate , bool * is_null )
4149
+ ExprState * default_estate , bool is_jsonb , bool * is_null )
4150
4150
{
4151
4151
* is_null = false;
4152
4152
4153
4153
switch (behavior -> btype )
4154
4154
{
4155
4155
case JSON_BEHAVIOR_EMPTY_ARRAY :
4156
- return JsonbPGetDatum (JsonbMakeEmptyArray ());
4156
+ return is_jsonb
4157
+ ? JsonbPGetDatum (JsonbMakeEmptyArray ())
4158
+ : PointerGetDatum (cstring_to_text ("[]" ));
4157
4159
4158
4160
case JSON_BEHAVIOR_EMPTY_OBJECT :
4159
- return JsonbPGetDatum (JsonbMakeEmptyObject ());
4161
+ return is_jsonb
4162
+ ? JsonbPGetDatum (JsonbMakeEmptyObject ())
4163
+ : PointerGetDatum (cstring_to_text ("{}" ));
4160
4164
4161
4165
case JSON_BEHAVIOR_TRUE :
4162
4166
return BoolGetDatum (true);
@@ -4183,17 +4187,20 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
4183
4187
*/
4184
4188
static Datum
4185
4189
ExecEvalJsonExprCoercion (ExprEvalStep * op , ExprContext * econtext ,
4186
- Datum res , bool * isNull )
4190
+ Datum res , bool * isNull , bool isJsonb )
4187
4191
{
4188
4192
JsonExpr * jexpr = op -> d .jsonexpr .jsexpr ;
4189
4193
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 );
4191
4196
4192
4197
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 ))))
4194
4200
{
4195
4201
/* strip quotes and call typinput function */
4196
- char * str = * isNull ? NULL : JsonbUnquote (jb );
4202
+ char * str = * isNull ? NULL :
4203
+ (isJsonb ? JsonbUnquote (jb ) : JsonUnquote (js ));
4197
4204
4198
4205
res = InputFunctionCall (& op -> d .jsonexpr .input .func , str ,
4199
4206
op -> d .jsonexpr .input .typioparam ,
@@ -4207,7 +4214,7 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
4207
4214
res = ExecEvalExpr (op -> d .jsonexpr .result_expr , econtext , isNull );
4208
4215
}
4209
4216
else if (coercion && coercion -> via_populate )
4210
- res = json_populate_type (res , JSONBOID ,
4217
+ res = json_populate_type (res , isJsonb ? JSONBOID : JSONOID ,
4211
4218
jexpr -> returning .typid ,
4212
4219
jexpr -> returning .typmod ,
4213
4220
& op -> d .jsonexpr .cache ,
@@ -4241,7 +4248,7 @@ EvalJsonPathVar(void *cxt, bool *isnull)
4241
4248
* corresponding SQL type and a pointer to the coercion state.
4242
4249
*/
4243
4250
Datum
4244
- ExecPrepareJsonItemCoercion (JsonbValue * item ,
4251
+ ExecPrepareJsonItemCoercion (JsonbValue * item , bool is_jsonb ,
4245
4252
JsonReturning * returning ,
4246
4253
struct JsonCoercionsState * coercions ,
4247
4254
struct JsonCoercionState * * pcoercion )
@@ -4250,8 +4257,14 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
4250
4257
Datum res ;
4251
4258
JsonbValue jbvbuf ;
4252
4259
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
+ }
4255
4268
4256
4269
/* get coercion state reference and datum of the corresponding SQL type */
4257
4270
switch (item -> type )
@@ -4308,7 +4321,18 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
4308
4321
case jbvObject :
4309
4322
case jbvBinary :
4310
4323
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
+ }
4312
4336
break ;
4313
4337
4314
4338
default :
@@ -4323,7 +4347,8 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
4323
4347
4324
4348
static Datum
4325
4349
ExecEvalJsonExpr (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 )
4327
4352
{
4328
4353
bool empty = false;
4329
4354
Datum res = (Datum ) 0 ;
@@ -4339,7 +4364,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4339
4364
if (isnull )
4340
4365
{
4341
4366
/* execute domain checks for NULLs */
4342
- (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4367
+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull ,
4368
+ isjsonb );
4343
4369
* resnull = true;
4344
4370
return (Datum ) 0 ;
4345
4371
}
@@ -4348,23 +4374,23 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4348
4374
switch (jexpr -> op )
4349
4375
{
4350
4376
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 );
4353
4379
* resnull = !DatumGetPointer (res );
4354
4380
break ;
4355
4381
4356
4382
case IS_JSON_VALUE :
4357
4383
{
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 );
4360
4386
struct JsonCoercionState * jcstate ;
4361
4387
4362
4388
if (!jbv )
4363
4389
break ;
4364
4390
4365
4391
* resnull = false;
4366
4392
4367
- res = ExecPrepareJsonItemCoercion (jbv ,
4393
+ res = ExecPrepareJsonItemCoercion (jbv , isjsonb ,
4368
4394
& op -> d .jsonexpr .jsexpr -> returning ,
4369
4395
& op -> d .jsonexpr .coercions ,
4370
4396
& jcstate );
@@ -4377,8 +4403,11 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4377
4403
jexpr -> returning .typid == JSONBOID )
4378
4404
{
4379
4405
/* 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 );
4382
4411
}
4383
4412
else if (jcstate -> estate )
4384
4413
{
@@ -4392,7 +4421,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4392
4421
break ;
4393
4422
4394
4423
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 ));
4396
4426
* resnull = false;
4397
4427
break ;
4398
4428
@@ -4411,14 +4441,15 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4411
4441
4412
4442
/* execute ON EMPTY behavior */
4413
4443
res = ExecEvalJsonBehavior (econtext , & jexpr -> on_empty ,
4414
- op -> d .jsonexpr .default_on_empty , resnull );
4444
+ op -> d .jsonexpr .default_on_empty ,
4445
+ isjsonb , resnull );
4415
4446
}
4416
4447
4417
4448
if (jexpr -> op != IS_JSON_EXISTS &&
4418
4449
(!empty ? jexpr -> op != IS_JSON_VALUE :
4419
4450
/* result is already coerced in DEFAULT behavior case */
4420
4451
jexpr -> on_empty .btype != JSON_BEHAVIOR_DEFAULT ))
4421
- res = ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4452
+ res = ExecEvalJsonExprCoercion (op , econtext , res , resnull , isjsonb );
4422
4453
4423
4454
return res ;
4424
4455
}
@@ -4441,14 +4472,18 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4441
4472
Datum res = (Datum ) 0 ;
4442
4473
JsonPath * path ;
4443
4474
ListCell * lc ;
4475
+ Oid formattedType = exprType (jexpr -> formatted_expr ?
4476
+ jexpr -> formatted_expr :
4477
+ jexpr -> raw_expr );
4478
+ bool isjsonb = formattedType == JSONBOID ;
4444
4479
4445
4480
* op -> resnull = true; /* until we get a result */
4446
4481
* op -> resvalue = (Datum ) 0 ;
4447
4482
4448
4483
if (op -> d .jsonexpr .raw_expr -> isnull || op -> d .jsonexpr .pathspec -> isnull )
4449
4484
{
4450
4485
/* execute domain checks for NULLs */
4451
- (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull );
4486
+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull , isjsonb );
4452
4487
4453
4488
Assert (* op -> resnull );
4454
4489
* op -> resnull = true;
@@ -4471,7 +4506,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4471
4506
if (!ExecEvalJsonNeedsSubTransaction (jexpr ))
4472
4507
{
4473
4508
/* 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 ,
4475
4510
op -> resnull );
4476
4511
}
4477
4512
else
@@ -4498,7 +4533,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4498
4533
PG_TRY ();
4499
4534
{
4500
4535
res = ExecEvalJsonExpr (state , op , newecontext , jexpr , path , item ,
4501
- op -> resnull );
4536
+ isjsonb , op -> resnull );
4502
4537
4503
4538
/* Commit the inner transaction, return to outer xact context */
4504
4539
ReleaseCurrentSubTransaction ();
@@ -4527,12 +4562,13 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4527
4562
/* Execute ON ERROR behavior. */
4528
4563
res = ExecEvalJsonBehavior (econtext , & jexpr -> on_error ,
4529
4564
op -> d .jsonexpr .default_on_error ,
4530
- op -> resnull );
4565
+ isjsonb , op -> resnull );
4531
4566
4532
4567
if (jexpr -> op != IS_JSON_EXISTS &&
4533
4568
/* result is already coerced in DEFAULT behavior case */
4534
4569
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 );
4536
4572
}
4537
4573
PG_END_TRY ();
4538
4574
}
0 commit comments