@@ -4163,17 +4163,21 @@ ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
4163
4163
*/
4164
4164
static Datum
4165
4165
ExecEvalJsonBehavior (ExprContext * econtext , JsonBehavior * behavior ,
4166
- ExprState * default_estate , bool * is_null )
4166
+ ExprState * default_estate , bool is_jsonb , bool * is_null )
4167
4167
{
4168
4168
* is_null = false;
4169
4169
4170
4170
switch (behavior -> btype )
4171
4171
{
4172
4172
case JSON_BEHAVIOR_EMPTY_ARRAY :
4173
- return JsonbPGetDatum (JsonbMakeEmptyArray ());
4173
+ return is_jsonb
4174
+ ? JsonbPGetDatum (JsonbMakeEmptyArray ())
4175
+ : PointerGetDatum (cstring_to_text ("[]" ));
4174
4176
4175
4177
case JSON_BEHAVIOR_EMPTY_OBJECT :
4176
- return JsonbPGetDatum (JsonbMakeEmptyObject ());
4178
+ return is_jsonb
4179
+ ? JsonbPGetDatum (JsonbMakeEmptyObject ())
4180
+ : PointerGetDatum (cstring_to_text ("{}" ));
4177
4181
4178
4182
case JSON_BEHAVIOR_TRUE :
4179
4183
return BoolGetDatum (true);
@@ -4200,17 +4204,20 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
4200
4204
*/
4201
4205
static Datum
4202
4206
ExecEvalJsonExprCoercion (ExprEvalStep * op , ExprContext * econtext ,
4203
- Datum res , bool * isNull )
4207
+ Datum res , bool * isNull , bool isJsonb )
4204
4208
{
4205
4209
JsonExpr * jexpr = op -> d .jsonexpr .jsexpr ;
4206
4210
JsonCoercion * coercion = jexpr -> result_coercion ;
4207
- Jsonb * jb = * isNull ? NULL : DatumGetJsonbP (res );
4211
+ Jsonb * jb = * isNull || !isJsonb ? NULL : DatumGetJsonbP (res );
4212
+ Json * js = * isNull || isJsonb ? NULL : DatumGetJsonP (res );
4208
4213
4209
4214
if ((coercion && coercion -> via_io ) ||
4210
- (jexpr -> omit_quotes && !* isNull && JB_ROOT_IS_SCALAR (jb )))
4215
+ (jexpr -> omit_quotes && !* isNull &&
4216
+ (isJsonb ? JB_ROOT_IS_SCALAR (jb ) : JsonContainerIsScalar (& js -> root ))))
4211
4217
{
4212
4218
/* strip quotes and call typinput function */
4213
- char * str = * isNull ? NULL : JsonbUnquote (jb );
4219
+ char * str = * isNull ? NULL :
4220
+ (isJsonb ? JsonbUnquote (jb ) : JsonUnquote (js ));
4214
4221
4215
4222
res = InputFunctionCall (& op -> d .jsonexpr .input .func , str ,
4216
4223
op -> d .jsonexpr .input .typioparam ,
@@ -4224,7 +4231,7 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
4224
4231
res = ExecEvalExpr (op -> d .jsonexpr .result_expr , econtext , isNull );
4225
4232
}
4226
4233
else if (coercion && coercion -> via_populate )
4227
- res = json_populate_type (res , JSONBOID ,
4234
+ res = json_populate_type (res , isJsonb ? JSONBOID : JSONOID ,
4228
4235
jexpr -> returning .typid ,
4229
4236
jexpr -> returning .typmod ,
4230
4237
& op -> d .jsonexpr .cache ,
@@ -4287,7 +4294,7 @@ EvalJsonPathVar(void *cxt, bool isJsonb, char *varName, int varNameLen,
4287
4294
* corresponding SQL type and a pointer to the coercion state.
4288
4295
*/
4289
4296
Datum
4290
- ExecPrepareJsonItemCoercion (JsonItem * item ,
4297
+ ExecPrepareJsonItemCoercion (JsonItem * item , bool is_jsonb ,
4291
4298
JsonReturning * returning ,
4292
4299
struct JsonCoercionsState * coercions ,
4293
4300
struct JsonCoercionState * * pcoercion )
@@ -4297,14 +4304,11 @@ ExecPrepareJsonItemCoercion(JsonItem *item,
4297
4304
JsonItem buf ;
4298
4305
4299
4306
if (JsonItemIsBinary (item ) &&
4300
- JsonContainerIsScalar (JsonItemBinary (item ).data ))
4301
- {
4302
- bool res PG_USED_FOR_ASSERTS_ONLY ;
4303
-
4304
- res = JsonbExtractScalar (JsonItemBinary (item ).data , JsonItemJbv (& buf ));
4307
+ (is_jsonb ?
4308
+ JsonbExtractScalar (JsonItemBinary (item ).data , JsonItemJbv (& buf )) :
4309
+ JsonExtractScalar ((JsonContainer * ) JsonItemBinary (item ).data ,
4310
+ JsonItemJbv (& buf ))))
4305
4311
item = & buf ;
4306
- Assert (res );
4307
- }
4308
4312
4309
4313
/* get coercion state reference and datum of the corresponding SQL type */
4310
4314
switch (JsonItemGetType (item ))
@@ -4361,7 +4365,7 @@ ExecPrepareJsonItemCoercion(JsonItem *item,
4361
4365
case jbvObject :
4362
4366
case jbvBinary :
4363
4367
coercion = & coercions -> composite ;
4364
- res = JsonbPGetDatum ( JsonItemToJsonb ( item ) );
4368
+ res = JsonItemToJsonxDatum ( item , is_jsonb );
4365
4369
break ;
4366
4370
4367
4371
default :
@@ -4376,7 +4380,8 @@ ExecPrepareJsonItemCoercion(JsonItem *item,
4376
4380
4377
4381
static Datum
4378
4382
ExecEvalJsonExpr (ExprState * state , ExprEvalStep * op , ExprContext * econtext ,
4379
- JsonExpr * jexpr , JsonPath * path , Datum item , bool * resnull )
4383
+ JsonExpr * jexpr , JsonPath * path , Datum item , bool isjsonb ,
4384
+ bool * resnull )
4380
4385
{
4381
4386
bool empty = false;
4382
4387
Datum res = (Datum ) 0 ;
@@ -4392,7 +4397,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4392
4397
if (isnull )
4393
4398
{
4394
4399
/* execute domain checks for NULLs */
4395
- (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4400
+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull ,
4401
+ isjsonb );
4396
4402
* resnull = true;
4397
4403
return (Datum ) 0 ;
4398
4404
}
@@ -4401,15 +4407,15 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4401
4407
switch (jexpr -> op )
4402
4408
{
4403
4409
case IS_JSON_QUERY :
4404
- res = JsonbPathQuery (item , path , jexpr -> wrapper , & empty ,
4405
- op -> d .jsonexpr .args );
4410
+ res = JsonPathQuery (item , path , jexpr -> wrapper , & empty ,
4411
+ op -> d .jsonexpr .args , isjsonb );
4406
4412
* resnull = !DatumGetPointer (res );
4407
4413
break ;
4408
4414
4409
4415
case IS_JSON_VALUE :
4410
4416
{
4411
- JsonItem * jbv = JsonbPathValue (item , path , & empty ,
4412
- op -> d .jsonexpr .args );
4417
+ JsonItem * jbv = JsonPathValue (item , path , & empty ,
4418
+ op -> d .jsonexpr .args , isjsonb );
4413
4419
struct JsonCoercionState * jcstate ;
4414
4420
4415
4421
if (!jbv ) /* NULL or empty */
@@ -4424,12 +4430,12 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4424
4430
jexpr -> returning .typid == JSONBOID )
4425
4431
{
4426
4432
/* Use result coercion from json[b] to the output type */
4427
- res = JsonbPGetDatum ( JsonItemToJsonb ( jbv ) );
4433
+ res = JsonItemToJsonxDatum ( jbv , isjsonb );
4428
4434
break ;
4429
4435
}
4430
4436
4431
4437
/* Use coercion from SQL/JSON item type to the output type */
4432
- res = ExecPrepareJsonItemCoercion (jbv ,
4438
+ res = ExecPrepareJsonItemCoercion (jbv , isjsonb ,
4433
4439
& op -> d .jsonexpr .jsexpr -> returning ,
4434
4440
& op -> d .jsonexpr .coercions ,
4435
4441
& jcstate );
@@ -4465,7 +4471,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4465
4471
4466
4472
case IS_JSON_EXISTS :
4467
4473
* resnull = false;
4468
- return BoolGetDatum (JsonbPathExists (item , path , op -> d .jsonexpr .args ));
4474
+ return BoolGetDatum (JsonPathExists (item , path , op -> d .jsonexpr .args ,
4475
+ isjsonb ));
4469
4476
4470
4477
default :
4471
4478
elog (ERROR , "unrecognized SQL/JSON expression op %d" , jexpr -> op );
@@ -4481,14 +4488,15 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4481
4488
4482
4489
/* execute ON EMPTY behavior */
4483
4490
res = ExecEvalJsonBehavior (econtext , & jexpr -> on_empty ,
4484
- op -> d .jsonexpr .default_on_empty , resnull );
4491
+ op -> d .jsonexpr .default_on_empty ,
4492
+ isjsonb , resnull );
4485
4493
4486
4494
/* result is already coerced in DEFAULT behavior case */
4487
4495
if (jexpr -> on_empty .btype == JSON_BEHAVIOR_DEFAULT )
4488
4496
return res ;
4489
4497
}
4490
4498
4491
- return ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4499
+ return ExecEvalJsonExprCoercion (op , econtext , res , resnull , isjsonb );
4492
4500
}
4493
4501
4494
4502
bool
@@ -4509,14 +4517,18 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4509
4517
Datum res = (Datum ) 0 ;
4510
4518
JsonPath * path ;
4511
4519
ListCell * lc ;
4520
+ Oid formattedType = exprType (jexpr -> formatted_expr ?
4521
+ jexpr -> formatted_expr :
4522
+ jexpr -> raw_expr );
4523
+ bool isjsonb = formattedType == JSONBOID ;
4512
4524
4513
4525
* op -> resnull = true; /* until we get a result */
4514
4526
* op -> resvalue = (Datum ) 0 ;
4515
4527
4516
4528
if (op -> d .jsonexpr .raw_expr -> isnull || op -> d .jsonexpr .pathspec -> isnull )
4517
4529
{
4518
4530
/* execute domain checks for NULLs */
4519
- (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull );
4531
+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull , isjsonb );
4520
4532
4521
4533
Assert (* op -> resnull );
4522
4534
* op -> resnull = true;
@@ -4539,7 +4551,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4539
4551
if (!ExecEvalJsonNeedsSubTransaction (jexpr ))
4540
4552
{
4541
4553
/* No need to use PG_TRY/PG_CATCH with subtransactions. */
4542
- res = ExecEvalJsonExpr (state , op , econtext , jexpr , path , item ,
4554
+ res = ExecEvalJsonExpr (state , op , econtext , jexpr , path , item , isjsonb ,
4543
4555
op -> resnull );
4544
4556
}
4545
4557
else
@@ -4558,7 +4570,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4558
4570
PG_TRY ();
4559
4571
{
4560
4572
res = ExecEvalJsonExpr (state , op , econtext , jexpr , path , item ,
4561
- op -> resnull );
4573
+ isjsonb , op -> resnull );
4562
4574
4563
4575
/* Commit the inner transaction, return to outer xact context */
4564
4576
ReleaseCurrentSubTransaction ();
@@ -4585,12 +4597,13 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4585
4597
/* Execute ON ERROR behavior. */
4586
4598
res = ExecEvalJsonBehavior (econtext , & jexpr -> on_error ,
4587
4599
op -> d .jsonexpr .default_on_error ,
4588
- op -> resnull );
4600
+ isjsonb , op -> resnull );
4589
4601
4590
4602
if (jexpr -> op != IS_JSON_EXISTS &&
4591
4603
/* result is already coerced in DEFAULT behavior case */
4592
4604
jexpr -> on_error .btype != JSON_BEHAVIOR_DEFAULT )
4593
- res = ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull );
4605
+ res = ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull ,
4606
+ isjsonb );
4594
4607
}
4595
4608
PG_END_TRY ();
4596
4609
}
0 commit comments