mirror of
https://github.com/postgres/postgres.git
synced 2026-04-15 22:10:45 -04:00
Make cast functions from jsonb error safe
This adjusts cast functions from jsonb to other types to support soft errors. This just involves some refactoring of the underlying helper functions to use ereturn. This is in preparation for a future feature where conversion errors in casts can be caught. Author: jian he <jian.universality@gmail.com> Reviewed-by: Amul Sul <sulamul@gmail.com> Reviewed-by: Corey Huinker <corey.huinker@gmail.com> Discussion: https://www.postgresql.org/message-id/flat/CADkLM%3Dfv1JfY4Ufa-jcwwNbjQixNViskQ8jZu3Tz_p656i_4hQ%40mail.gmail.com
This commit is contained in:
parent
999dec9ec6
commit
10e4d8aaf4
1 changed files with 18 additions and 17 deletions
|
|
@ -1785,8 +1785,8 @@ JsonbExtractScalar(JsonbContainer *jbc, JsonbValue *res)
|
|||
/*
|
||||
* Emit correct, translatable cast error message
|
||||
*/
|
||||
static void
|
||||
cannotCastJsonbValue(enum jbvType type, const char *sqltype)
|
||||
static Datum
|
||||
cannotCastJsonbValue(enum jbvType type, const char *sqltype, Node *escontext)
|
||||
{
|
||||
static const struct
|
||||
{
|
||||
|
|
@ -1807,12 +1807,13 @@ cannotCastJsonbValue(enum jbvType type, const char *sqltype)
|
|||
|
||||
for (i = 0; i < lengthof(messages); i++)
|
||||
if (messages[i].type == type)
|
||||
ereport(ERROR,
|
||||
ereturn(escontext, (Datum) 0,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg(messages[i].msg, sqltype)));
|
||||
|
||||
/* should be unreachable */
|
||||
elog(ERROR, "unknown jsonb type: %d", (int) type);
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
Datum
|
||||
|
|
@ -1822,7 +1823,7 @@ jsonb_bool(PG_FUNCTION_ARGS)
|
|||
JsonbValue v;
|
||||
|
||||
if (!JsonbExtractScalar(&in->root, &v))
|
||||
cannotCastJsonbValue(v.type, "boolean");
|
||||
return cannotCastJsonbValue(v.type, "boolean", fcinfo->context);
|
||||
|
||||
if (v.type == jbvNull)
|
||||
{
|
||||
|
|
@ -1831,7 +1832,7 @@ jsonb_bool(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
if (v.type != jbvBool)
|
||||
cannotCastJsonbValue(v.type, "boolean");
|
||||
return cannotCastJsonbValue(v.type, "boolean", fcinfo->context);
|
||||
|
||||
PG_FREE_IF_COPY(in, 0);
|
||||
|
||||
|
|
@ -1846,7 +1847,7 @@ jsonb_numeric(PG_FUNCTION_ARGS)
|
|||
Numeric retValue;
|
||||
|
||||
if (!JsonbExtractScalar(&in->root, &v))
|
||||
cannotCastJsonbValue(v.type, "numeric");
|
||||
return cannotCastJsonbValue(v.type, "numeric", fcinfo->context);
|
||||
|
||||
if (v.type == jbvNull)
|
||||
{
|
||||
|
|
@ -1855,7 +1856,7 @@ jsonb_numeric(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
if (v.type != jbvNumeric)
|
||||
cannotCastJsonbValue(v.type, "numeric");
|
||||
return cannotCastJsonbValue(v.type, "numeric", fcinfo->context);
|
||||
|
||||
/*
|
||||
* v.val.numeric points into jsonb body, so we need to make a copy to
|
||||
|
|
@ -1876,7 +1877,7 @@ jsonb_int2(PG_FUNCTION_ARGS)
|
|||
Datum retValue;
|
||||
|
||||
if (!JsonbExtractScalar(&in->root, &v))
|
||||
cannotCastJsonbValue(v.type, "smallint");
|
||||
return cannotCastJsonbValue(v.type, "smallint", fcinfo->context);
|
||||
|
||||
if (v.type == jbvNull)
|
||||
{
|
||||
|
|
@ -1885,7 +1886,7 @@ jsonb_int2(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
if (v.type != jbvNumeric)
|
||||
cannotCastJsonbValue(v.type, "smallint");
|
||||
return cannotCastJsonbValue(v.type, "smallint", fcinfo->context);
|
||||
|
||||
retValue = DirectFunctionCall1(numeric_int2,
|
||||
NumericGetDatum(v.val.numeric));
|
||||
|
|
@ -1903,7 +1904,7 @@ jsonb_int4(PG_FUNCTION_ARGS)
|
|||
Datum retValue;
|
||||
|
||||
if (!JsonbExtractScalar(&in->root, &v))
|
||||
cannotCastJsonbValue(v.type, "integer");
|
||||
return cannotCastJsonbValue(v.type, "integer", fcinfo->context);
|
||||
|
||||
if (v.type == jbvNull)
|
||||
{
|
||||
|
|
@ -1912,7 +1913,7 @@ jsonb_int4(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
if (v.type != jbvNumeric)
|
||||
cannotCastJsonbValue(v.type, "integer");
|
||||
return cannotCastJsonbValue(v.type, "integer", fcinfo->context);
|
||||
|
||||
retValue = DirectFunctionCall1(numeric_int4,
|
||||
NumericGetDatum(v.val.numeric));
|
||||
|
|
@ -1930,7 +1931,7 @@ jsonb_int8(PG_FUNCTION_ARGS)
|
|||
Datum retValue;
|
||||
|
||||
if (!JsonbExtractScalar(&in->root, &v))
|
||||
cannotCastJsonbValue(v.type, "bigint");
|
||||
return cannotCastJsonbValue(v.type, "bigint", fcinfo->context);
|
||||
|
||||
if (v.type == jbvNull)
|
||||
{
|
||||
|
|
@ -1939,7 +1940,7 @@ jsonb_int8(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
if (v.type != jbvNumeric)
|
||||
cannotCastJsonbValue(v.type, "bigint");
|
||||
return cannotCastJsonbValue(v.type, "bigint", fcinfo->context);
|
||||
|
||||
retValue = DirectFunctionCall1(numeric_int8,
|
||||
NumericGetDatum(v.val.numeric));
|
||||
|
|
@ -1957,7 +1958,7 @@ jsonb_float4(PG_FUNCTION_ARGS)
|
|||
Datum retValue;
|
||||
|
||||
if (!JsonbExtractScalar(&in->root, &v))
|
||||
cannotCastJsonbValue(v.type, "real");
|
||||
return cannotCastJsonbValue(v.type, "real", fcinfo->context);
|
||||
|
||||
if (v.type == jbvNull)
|
||||
{
|
||||
|
|
@ -1966,7 +1967,7 @@ jsonb_float4(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
if (v.type != jbvNumeric)
|
||||
cannotCastJsonbValue(v.type, "real");
|
||||
return cannotCastJsonbValue(v.type, "real", fcinfo->context);
|
||||
|
||||
retValue = DirectFunctionCall1(numeric_float4,
|
||||
NumericGetDatum(v.val.numeric));
|
||||
|
|
@ -1984,7 +1985,7 @@ jsonb_float8(PG_FUNCTION_ARGS)
|
|||
Datum retValue;
|
||||
|
||||
if (!JsonbExtractScalar(&in->root, &v))
|
||||
cannotCastJsonbValue(v.type, "double precision");
|
||||
return cannotCastJsonbValue(v.type, "double precision", fcinfo->context);
|
||||
|
||||
if (v.type == jbvNull)
|
||||
{
|
||||
|
|
@ -1993,7 +1994,7 @@ jsonb_float8(PG_FUNCTION_ARGS)
|
|||
}
|
||||
|
||||
if (v.type != jbvNumeric)
|
||||
cannotCastJsonbValue(v.type, "double precision");
|
||||
return cannotCastJsonbValue(v.type, "double precision", fcinfo->context);
|
||||
|
||||
retValue = DirectFunctionCall1(numeric_float8,
|
||||
NumericGetDatum(v.val.numeric));
|
||||
|
|
|
|||
Loading…
Reference in a new issue