@@ -4150,17 +4150,21 @@ ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
4150
4150
*/
4151
4151
static Datum
4152
4152
ExecEvalJsonBehavior (ExprContext * econtext , JsonBehavior * behavior ,
4153
- ExprState * default_estate , bool * is_null )
4153
+ ExprState * default_estate , bool is_jsonb , bool * is_null )
4154
4154
{
4155
4155
* is_null = false;
4156
4156
4157
4157
switch (behavior -> btype )
4158
4158
{
4159
4159
case JSON_BEHAVIOR_EMPTY_ARRAY :
4160
- return JsonbPGetDatum (JsonbMakeEmptyArray ());
4160
+ return is_jsonb
4161
+ ? JsonbPGetDatum (JsonbMakeEmptyArray ())
4162
+ : PointerGetDatum (cstring_to_text ("[]" ));
4161
4163
4162
4164
case JSON_BEHAVIOR_EMPTY_OBJECT :
4163
- return JsonbPGetDatum (JsonbMakeEmptyObject ());
4165
+ return is_jsonb
4166
+ ? JsonbPGetDatum (JsonbMakeEmptyObject ())
4167
+ : PointerGetDatum (cstring_to_text ("{}" ));
4164
4168
4165
4169
case JSON_BEHAVIOR_TRUE :
4166
4170
return BoolGetDatum (true);
@@ -4187,17 +4191,20 @@ ExecEvalJsonBehavior(ExprContext *econtext, JsonBehavior *behavior,
4187
4191
*/
4188
4192
static Datum
4189
4193
ExecEvalJsonExprCoercion (ExprEvalStep * op , ExprContext * econtext ,
4190
- Datum res , bool * isNull )
4194
+ Datum res , bool * isNull , bool isJsonb )
4191
4195
{
4192
4196
JsonExpr * jexpr = op -> d .jsonexpr .jsexpr ;
4193
4197
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 );
4195
4200
4196
4201
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 ))))
4198
4204
{
4199
4205
/* strip quotes and call typinput function */
4200
- char * str = * isNull ? NULL : JsonbUnquote (jb );
4206
+ char * str = * isNull ? NULL :
4207
+ (isJsonb ? JsonbUnquote (jb ) : JsonUnquote (js ));
4201
4208
4202
4209
res = InputFunctionCall (& op -> d .jsonexpr .input .func , str ,
4203
4210
op -> d .jsonexpr .input .typioparam ,
@@ -4211,7 +4218,7 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
4211
4218
res = ExecEvalExpr (op -> d .jsonexpr .result_expr , econtext , isNull );
4212
4219
}
4213
4220
else if (coercion && coercion -> via_populate )
4214
- res = json_populate_type (res , JSONBOID ,
4221
+ res = json_populate_type (res , isJsonb ? JSONBOID : JSONOID ,
4215
4222
jexpr -> returning .typid ,
4216
4223
jexpr -> returning .typmod ,
4217
4224
& op -> d .jsonexpr .cache ,
@@ -4245,7 +4252,7 @@ EvalJsonPathVar(void *cxt, bool *isnull)
4245
4252
* corresponding SQL type and a pointer to the coercion state.
4246
4253
*/
4247
4254
Datum
4248
- ExecPrepareJsonItemCoercion (JsonbValue * item ,
4255
+ ExecPrepareJsonItemCoercion (JsonbValue * item , bool is_jsonb ,
4249
4256
JsonReturning * returning ,
4250
4257
struct JsonCoercionsState * coercions ,
4251
4258
struct JsonCoercionState * * pcoercion )
@@ -4254,8 +4261,14 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
4254
4261
Datum res ;
4255
4262
JsonbValue jbvbuf ;
4256
4263
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
+ }
4259
4272
4260
4273
/* get coercion state reference and datum of the corresponding SQL type */
4261
4274
switch (item -> type )
@@ -4312,7 +4325,18 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
4312
4325
case jbvObject :
4313
4326
case jbvBinary :
4314
4327
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
+ }
4316
4340
break ;
4317
4341
4318
4342
default :
@@ -4327,7 +4351,8 @@ ExecPrepareJsonItemCoercion(JsonbValue *item,
4327
4351
4328
4352
static Datum
4329
4353
ExecEvalJsonExpr (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 )
4331
4356
{
4332
4357
bool empty = false;
4333
4358
Datum res = (Datum ) 0 ;
@@ -4343,7 +4368,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4343
4368
if (isnull )
4344
4369
{
4345
4370
/* execute domain checks for NULLs */
4346
- (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4371
+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , resnull ,
4372
+ isjsonb );
4347
4373
* resnull = true;
4348
4374
return (Datum ) 0 ;
4349
4375
}
@@ -4352,15 +4378,15 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4352
4378
switch (jexpr -> op )
4353
4379
{
4354
4380
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 );
4357
4383
* resnull = !DatumGetPointer (res );
4358
4384
break ;
4359
4385
4360
4386
case IS_JSON_VALUE :
4361
4387
{
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 );
4364
4390
struct JsonCoercionState * jcstate ;
4365
4391
4366
4392
if (!jbv ) /* NULL or empty */
@@ -4375,12 +4401,14 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4375
4401
jexpr -> returning .typid == JSONBOID )
4376
4402
{
4377
4403
/* 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 ));
4379
4407
break ;
4380
4408
}
4381
4409
4382
4410
/* Use coercion from SQL/JSON item type to the output type */
4383
- res = ExecPrepareJsonItemCoercion (jbv ,
4411
+ res = ExecPrepareJsonItemCoercion (jbv , isjsonb ,
4384
4412
& op -> d .jsonexpr .jsexpr -> returning ,
4385
4413
& op -> d .jsonexpr .coercions ,
4386
4414
& jcstate );
@@ -4416,7 +4444,8 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4416
4444
4417
4445
case IS_JSON_EXISTS :
4418
4446
* 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 ));
4420
4449
4421
4450
default :
4422
4451
elog (ERROR , "unrecognized SQL/JSON expression op %d" , jexpr -> op );
@@ -4432,14 +4461,15 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
4432
4461
4433
4462
/* execute ON EMPTY behavior */
4434
4463
res = ExecEvalJsonBehavior (econtext , & jexpr -> on_empty ,
4435
- op -> d .jsonexpr .default_on_empty , resnull );
4464
+ op -> d .jsonexpr .default_on_empty ,
4465
+ isjsonb , resnull );
4436
4466
4437
4467
/* result is already coerced in DEFAULT behavior case */
4438
4468
if (jexpr -> on_empty .btype == JSON_BEHAVIOR_DEFAULT )
4439
4469
return res ;
4440
4470
}
4441
4471
4442
- return ExecEvalJsonExprCoercion (op , econtext , res , resnull );
4472
+ return ExecEvalJsonExprCoercion (op , econtext , res , resnull , isjsonb );
4443
4473
}
4444
4474
4445
4475
bool
@@ -4460,14 +4490,18 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4460
4490
Datum res = (Datum ) 0 ;
4461
4491
JsonPath * path ;
4462
4492
ListCell * lc ;
4493
+ Oid formattedType = exprType (jexpr -> formatted_expr ?
4494
+ jexpr -> formatted_expr :
4495
+ jexpr -> raw_expr );
4496
+ bool isjsonb = formattedType == JSONBOID ;
4463
4497
4464
4498
* op -> resnull = true; /* until we get a result */
4465
4499
* op -> resvalue = (Datum ) 0 ;
4466
4500
4467
4501
if (op -> d .jsonexpr .raw_expr -> isnull || op -> d .jsonexpr .pathspec -> isnull )
4468
4502
{
4469
4503
/* execute domain checks for NULLs */
4470
- (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull );
4504
+ (void ) ExecEvalJsonExprCoercion (op , econtext , res , op -> resnull , isjsonb );
4471
4505
4472
4506
Assert (* op -> resnull );
4473
4507
* op -> resnull = true;
@@ -4490,7 +4524,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4490
4524
if (!ExecEvalJsonNeedsSubTransaction (jexpr ))
4491
4525
{
4492
4526
/* 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 ,
4494
4528
op -> resnull );
4495
4529
}
4496
4530
else
@@ -4509,7 +4543,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4509
4543
PG_TRY ();
4510
4544
{
4511
4545
res = ExecEvalJsonExpr (state , op , econtext , jexpr , path , item ,
4512
- op -> resnull );
4546
+ isjsonb , op -> resnull );
4513
4547
4514
4548
/* Commit the inner transaction, return to outer xact context */
4515
4549
ReleaseCurrentSubTransaction ();
@@ -4536,12 +4570,13 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
4536
4570
/* Execute ON ERROR behavior. */
4537
4571
res = ExecEvalJsonBehavior (econtext , & jexpr -> on_error ,
4538
4572
op -> d .jsonexpr .default_on_error ,
4539
- op -> resnull );
4573
+ isjsonb , op -> resnull );
4540
4574
4541
4575
if (jexpr -> op != IS_JSON_EXISTS &&
4542
4576
/* result is already coerced in DEFAULT behavior case */
4543
4577
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 );
4545
4580
}
4546
4581
PG_END_TRY ();
4547
4582
}
0 commit comments