Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d1dc4b5

Browse files
author
Nikita Glukhov
committed
Fix JSON_VALUE coercion via IO
1 parent 2d13d03 commit d1dc4b5

File tree

3 files changed

+39
-28
lines changed

3 files changed

+39
-28
lines changed

src/backend/executor/execExprInterp.c

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4412,26 +4412,44 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
44124412
op->d.jsonexpr.args);
44134413
struct JsonCoercionState *jcstate;
44144414

4415-
if (!jbv)
4415+
if (!jbv) /* NULL or empty */
44164416
break;
44174417

4418+
Assert(!empty);
4419+
44184420
*resnull = false;
44194421

4422+
/* coerce item datum to the output type */
4423+
if (jexpr->returning.typid == JSONOID ||
4424+
jexpr->returning.typid == JSONBOID)
4425+
{
4426+
/* Use result coercion from json[b] to the output type */
4427+
res = JsonbPGetDatum(JsonItemToJsonb(jbv));
4428+
break;
4429+
}
4430+
4431+
/* Use coercion from SQL/JSON item type to the output type */
44204432
res = ExecPrepareJsonItemCoercion(jbv,
44214433
&op->d.jsonexpr.jsexpr->returning,
44224434
&op->d.jsonexpr.coercions,
44234435
&jcstate);
44244436

4425-
/* coerce item datum to the output type */
4426-
if ((jcstate->coercion &&
4437+
if (jcstate->coercion &&
44274438
(jcstate->coercion->via_io ||
4428-
jcstate->coercion->via_populate)) || /* ignored for scalars jsons */
4429-
jexpr->returning.typid == JSONOID ||
4430-
jexpr->returning.typid == JSONBOID)
4439+
jcstate->coercion->via_populate))
44314440
{
4432-
/* use coercion via I/O from json[b] to the output type */
4433-
res = JsonbPGetDatum(JsonItemToJsonb(jbv));
4434-
res = ExecEvalJsonExprCoercion(op, econtext, res, resnull);
4441+
/*
4442+
* Coercion via I/O means here that the cast to the target
4443+
* type simply does not exist.
4444+
*/
4445+
ereport(ERROR,
4446+
/*
4447+
* XXX Standard says about a separate error code
4448+
* ERRCODE_JSON_ITEM_CANNOT_BE_CAST_TO_TARGET_TYPE
4449+
* but does not define its number.
4450+
*/
4451+
(errcode(ERRCODE_JSON_SCALAR_REQUIRED),
4452+
errmsg("SQL/JSON item cannot be cast to target type")));
44354453
}
44364454
else if (jcstate->estate)
44374455
{
@@ -4441,17 +4459,16 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
44414459
res = ExecEvalExpr(jcstate->estate, econtext, resnull);
44424460
}
44434461
/* else no coercion */
4462+
4463+
return res;
44444464
}
4445-
break;
44464465

44474466
case IS_JSON_EXISTS:
4448-
res = BoolGetDatum(JsonbPathExists(item, path, op->d.jsonexpr.args));
44494467
*resnull = false;
4450-
break;
4468+
return BoolGetDatum(JsonbPathExists(item, path, op->d.jsonexpr.args));
44514469

44524470
default:
4453-
elog(ERROR, "unrecognized SQL/JSON expression op %d",
4454-
jexpr->op);
4471+
elog(ERROR, "unrecognized SQL/JSON expression op %d", jexpr->op);
44554472
return (Datum) 0;
44564473
}
44574474

@@ -4465,15 +4482,13 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
44654482
/* execute ON EMPTY behavior */
44664483
res = ExecEvalJsonBehavior(econtext, &jexpr->on_empty,
44674484
op->d.jsonexpr.default_on_empty, resnull);
4468-
}
44694485

4470-
if (jexpr->op != IS_JSON_EXISTS &&
4471-
(!empty ? jexpr->op != IS_JSON_VALUE :
4472-
/* result is already coerced in DEFAULT behavior case */
4473-
jexpr->on_empty.btype != JSON_BEHAVIOR_DEFAULT))
4474-
res = ExecEvalJsonExprCoercion(op, econtext, res, resnull);
4486+
/* result is already coerced in DEFAULT behavior case */
4487+
if (jexpr->on_empty.btype == JSON_BEHAVIOR_DEFAULT)
4488+
return res;
4489+
}
44754490

4476-
return res;
4491+
return ExecEvalJsonExprCoercion(op, econtext, res, resnull);
44774492
}
44784493

44794494
bool

src/test/regress/expected/jsonb_sqljson.out

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -190,12 +190,8 @@ SELECT JSON_VALUE(jsonb '123', '$' RETURNING text);
190190
(1 row)
191191

192192
/* jsonb bytea ??? */
193-
SELECT JSON_VALUE(jsonb '123', '$' RETURNING bytea);
194-
json_value
195-
------------
196-
\x313233
197-
(1 row)
198-
193+
SELECT JSON_VALUE(jsonb '123', '$' RETURNING bytea ERROR ON ERROR);
194+
ERROR: SQL/JSON item cannot be cast to target type
199195
SELECT JSON_VALUE(jsonb '1.23', '$');
200196
json_value
201197
------------

src/test/regress/sql/jsonb_sqljson.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ SELECT JSON_VALUE(jsonb '123', '$');
4646
SELECT JSON_VALUE(jsonb '123', '$' RETURNING int) + 234;
4747
SELECT JSON_VALUE(jsonb '123', '$' RETURNING text);
4848
/* jsonb bytea ??? */
49-
SELECT JSON_VALUE(jsonb '123', '$' RETURNING bytea);
49+
SELECT JSON_VALUE(jsonb '123', '$' RETURNING bytea ERROR ON ERROR);
5050

5151
SELECT JSON_VALUE(jsonb '1.23', '$');
5252
SELECT JSON_VALUE(jsonb '1.23', '$' RETURNING int);

0 commit comments

Comments
 (0)