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

Commit aff8ccf

Browse files
author
Nikita Glukhov
committed
Fix JSON_VALUE coercion via IO
1 parent 29f710c commit aff8ccf

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
@@ -4725,26 +4725,44 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
47254725
op->d.jsonexpr.args);
47264726
struct JsonCoercionState *jcstate;
47274727

4728-
if (!jbv)
4728+
if (!jbv) /* NULL or empty */
47294729
break;
47304730

4731+
Assert(!empty);
4732+
47314733
*resnull = false;
47324734

4735+
/* coerce item datum to the output type */
4736+
if (jexpr->returning->typid == JSONOID ||
4737+
jexpr->returning->typid == JSONBOID)
4738+
{
4739+
/* Use result coercion from json[b] to the output type */
4740+
res = JsonbPGetDatum(JsonbValueToJsonb(jbv));
4741+
break;
4742+
}
4743+
4744+
/* Use coercion from SQL/JSON item type to the output type */
47334745
res = ExecPrepareJsonItemCoercion(jbv,
47344746
op->d.jsonexpr.jsexpr->returning,
47354747
&op->d.jsonexpr.coercions,
47364748
&jcstate);
47374749

4738-
/* coerce item datum to the output type */
4739-
if ((jcstate->coercion &&
4750+
if (jcstate->coercion &&
47404751
(jcstate->coercion->via_io ||
4741-
jcstate->coercion->via_populate)) || /* ignored for scalars jsons */
4742-
jexpr->returning->typid == JSONOID ||
4743-
jexpr->returning->typid == JSONBOID)
4752+
jcstate->coercion->via_populate))
47444753
{
4745-
/* use coercion via I/O from json[b] to the output type */
4746-
res = JsonbPGetDatum(JsonbValueToJsonb(jbv));
4747-
res = ExecEvalJsonExprCoercion(op, econtext, res, resnull);
4754+
/*
4755+
* Coercion via I/O means here that the cast to the target
4756+
* type simply does not exist.
4757+
*/
4758+
ereport(ERROR,
4759+
/*
4760+
* XXX Standard says about a separate error code
4761+
* ERRCODE_SQL_JSON_ITEM_CANNOT_BE_CAST_TO_TARGET_TYPE
4762+
* but does not define its number.
4763+
*/
4764+
(errcode(ERRCODE_SQL_JSON_SCALAR_REQUIRED),
4765+
errmsg("SQL/JSON item cannot be cast to target type")));
47484766
}
47494767
else if (jcstate->estate)
47504768
{
@@ -4754,17 +4772,16 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
47544772
res = ExecEvalExpr(jcstate->estate, econtext, resnull);
47554773
}
47564774
/* else no coercion */
4775+
4776+
return res;
47574777
}
4758-
break;
47594778

47604779
case IS_JSON_EXISTS:
4761-
res = BoolGetDatum(JsonbPathExists(item, path, op->d.jsonexpr.args));
47624780
*resnull = false;
4763-
break;
4781+
return BoolGetDatum(JsonbPathExists(item, path, op->d.jsonexpr.args));
47644782

47654783
default:
4766-
elog(ERROR, "unrecognized SQL/JSON expression op %d",
4767-
jexpr->op);
4784+
elog(ERROR, "unrecognized SQL/JSON expression op %d", jexpr->op);
47684785
return (Datum) 0;
47694786
}
47704787

@@ -4780,15 +4797,13 @@ ExecEvalJsonExpr(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
47804797
/* execute ON EMPTY behavior */
47814798
res = ExecEvalJsonBehavior(econtext, jexpr->on_empty,
47824799
op->d.jsonexpr.default_on_empty, resnull);
4783-
}
47844800

4785-
if (jexpr->op != IS_JSON_EXISTS &&
4786-
(!empty ? jexpr->op != IS_JSON_VALUE :
4787-
/* result is already coerced in DEFAULT behavior case */
4788-
jexpr->on_empty->btype != JSON_BEHAVIOR_DEFAULT))
4789-
res = ExecEvalJsonExprCoercion(op, econtext, res, resnull);
4801+
/* result is already coerced in DEFAULT behavior case */
4802+
if (jexpr->on_empty->btype == JSON_BEHAVIOR_DEFAULT)
4803+
return res;
4804+
}
47904805

4791-
return res;
4806+
return ExecEvalJsonExprCoercion(op, econtext, res, resnull);
47924807
}
47934808

47944809
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)