mirror of
https://github.com/postgres/postgres.git
synced 2025-10-10 00:03:27 -04:00
Switch some numeric-related functions to use soft error reporting
This commit changes some functions related to the data type numeric to use the soft error reporting rather than a custom boolean flag (called "have_error") that callers of these functions could rely on to bypass the generation of ERROR reports, letting the callers do their own error handling (timestamp, jsonpath and numeric_to_char() require them). This results in the removal of some boilerplate code that was required to handle both the ereport() and the "have_error" code paths bypassing ereport(), unifying everything under the soft error reporting facility. While on it, some duplicated error messages are removed. The function upgraded in this commit were suffixed with "_opt_error" in their names. They are renamed to "_safe" instead. This change relies on d9f7f5d32f20, that has introduced the soft error reporting infrastructure. Author: Amul Sul <sulamul@gmail.com> Reviewed-by: Dean Rasheed <dean.a.rasheed@gmail.com> Discussion: https://postgr.es/m/CAAJ_b96No5h5tRuR+KhcC44YcYUCw8WAHuLoqqyyop8_k3+JDQ@mail.gmail.com
This commit is contained in:
parent
ae45312008
commit
4246a977ba
@ -6389,12 +6389,12 @@ numeric_to_char(PG_FUNCTION_ARGS)
|
|||||||
if (IS_ROMAN(&Num))
|
if (IS_ROMAN(&Num))
|
||||||
{
|
{
|
||||||
int32 intvalue;
|
int32 intvalue;
|
||||||
bool err;
|
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||||
|
|
||||||
/* Round and convert to int */
|
/* Round and convert to int */
|
||||||
intvalue = numeric_int4_opt_error(value, &err);
|
intvalue = numeric_int4_safe(value, (Node *) &escontext);
|
||||||
/* On overflow, just use PG_INT32_MAX; int_to_roman will cope */
|
/* On overflow, just use PG_INT32_MAX; int_to_roman will cope */
|
||||||
if (err)
|
if (escontext.error_occurred)
|
||||||
intvalue = PG_INT32_MAX;
|
intvalue = PG_INT32_MAX;
|
||||||
numstr = int_to_roman(intvalue);
|
numstr = int_to_roman(intvalue);
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,8 @@ typedef JsonPathBool (*JsonPathPredicateCallback) (JsonPathItem *jsp,
|
|||||||
JsonbValue *larg,
|
JsonbValue *larg,
|
||||||
JsonbValue *rarg,
|
JsonbValue *rarg,
|
||||||
void *param);
|
void *param);
|
||||||
typedef Numeric (*BinaryArithmFunc) (Numeric num1, Numeric num2, bool *error);
|
typedef Numeric (*BinaryArithmFunc) (Numeric num1, Numeric num2,
|
||||||
|
Node *escontext);
|
||||||
|
|
||||||
static JsonPathExecResult executeJsonPath(JsonPath *path, void *vars,
|
static JsonPathExecResult executeJsonPath(JsonPath *path, void *vars,
|
||||||
JsonPathGetVarCallback getVar,
|
JsonPathGetVarCallback getVar,
|
||||||
@ -808,23 +809,23 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
|
|||||||
|
|
||||||
case jpiAdd:
|
case jpiAdd:
|
||||||
return executeBinaryArithmExpr(cxt, jsp, jb,
|
return executeBinaryArithmExpr(cxt, jsp, jb,
|
||||||
numeric_add_opt_error, found);
|
numeric_add_safe, found);
|
||||||
|
|
||||||
case jpiSub:
|
case jpiSub:
|
||||||
return executeBinaryArithmExpr(cxt, jsp, jb,
|
return executeBinaryArithmExpr(cxt, jsp, jb,
|
||||||
numeric_sub_opt_error, found);
|
numeric_sub_safe, found);
|
||||||
|
|
||||||
case jpiMul:
|
case jpiMul:
|
||||||
return executeBinaryArithmExpr(cxt, jsp, jb,
|
return executeBinaryArithmExpr(cxt, jsp, jb,
|
||||||
numeric_mul_opt_error, found);
|
numeric_mul_safe, found);
|
||||||
|
|
||||||
case jpiDiv:
|
case jpiDiv:
|
||||||
return executeBinaryArithmExpr(cxt, jsp, jb,
|
return executeBinaryArithmExpr(cxt, jsp, jb,
|
||||||
numeric_div_opt_error, found);
|
numeric_div_safe, found);
|
||||||
|
|
||||||
case jpiMod:
|
case jpiMod:
|
||||||
return executeBinaryArithmExpr(cxt, jsp, jb,
|
return executeBinaryArithmExpr(cxt, jsp, jb,
|
||||||
numeric_mod_opt_error, found);
|
numeric_mod_safe, found);
|
||||||
|
|
||||||
case jpiPlus:
|
case jpiPlus:
|
||||||
return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
|
return executeUnaryArithmExpr(cxt, jsp, jb, NULL, found);
|
||||||
@ -1269,11 +1270,12 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
|
|||||||
|
|
||||||
if (jb->type == jbvNumeric)
|
if (jb->type == jbvNumeric)
|
||||||
{
|
{
|
||||||
bool have_error;
|
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||||
int64 val;
|
int64 val;
|
||||||
|
|
||||||
val = numeric_int8_opt_error(jb->val.numeric, &have_error);
|
val = numeric_int8_safe(jb->val.numeric,
|
||||||
if (have_error)
|
(Node *) &escontext);
|
||||||
|
if (escontext.error_occurred)
|
||||||
RETURN_ERROR(ereport(ERROR,
|
RETURN_ERROR(ereport(ERROR,
|
||||||
(errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
|
(errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
|
||||||
errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
|
errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
|
||||||
@ -1466,7 +1468,6 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
|
|||||||
Datum dtypmod;
|
Datum dtypmod;
|
||||||
int32 precision;
|
int32 precision;
|
||||||
int32 scale = 0;
|
int32 scale = 0;
|
||||||
bool have_error;
|
|
||||||
bool noerr;
|
bool noerr;
|
||||||
ArrayType *arrtypmod;
|
ArrayType *arrtypmod;
|
||||||
Datum datums[2];
|
Datum datums[2];
|
||||||
@ -1478,9 +1479,9 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
|
|||||||
if (elem.type != jpiNumeric)
|
if (elem.type != jpiNumeric)
|
||||||
elog(ERROR, "invalid jsonpath item type for .decimal() precision");
|
elog(ERROR, "invalid jsonpath item type for .decimal() precision");
|
||||||
|
|
||||||
precision = numeric_int4_opt_error(jspGetNumeric(&elem),
|
precision = numeric_int4_safe(jspGetNumeric(&elem),
|
||||||
&have_error);
|
(Node *) &escontext);
|
||||||
if (have_error)
|
if (escontext.error_occurred)
|
||||||
RETURN_ERROR(ereport(ERROR,
|
RETURN_ERROR(ereport(ERROR,
|
||||||
(errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
|
(errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
|
||||||
errmsg("precision of jsonpath item method .%s() is out of range for type integer",
|
errmsg("precision of jsonpath item method .%s() is out of range for type integer",
|
||||||
@ -1492,9 +1493,9 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
|
|||||||
if (elem.type != jpiNumeric)
|
if (elem.type != jpiNumeric)
|
||||||
elog(ERROR, "invalid jsonpath item type for .decimal() scale");
|
elog(ERROR, "invalid jsonpath item type for .decimal() scale");
|
||||||
|
|
||||||
scale = numeric_int4_opt_error(jspGetNumeric(&elem),
|
scale = numeric_int4_safe(jspGetNumeric(&elem),
|
||||||
&have_error);
|
(Node *) &escontext);
|
||||||
if (have_error)
|
if (escontext.error_occurred)
|
||||||
RETURN_ERROR(ereport(ERROR,
|
RETURN_ERROR(ereport(ERROR,
|
||||||
(errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
|
(errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
|
||||||
errmsg("scale of jsonpath item method .%s() is out of range for type integer",
|
errmsg("scale of jsonpath item method .%s() is out of range for type integer",
|
||||||
@ -1550,11 +1551,12 @@ executeItemOptUnwrapTarget(JsonPathExecContext *cxt, JsonPathItem *jsp,
|
|||||||
|
|
||||||
if (jb->type == jbvNumeric)
|
if (jb->type == jbvNumeric)
|
||||||
{
|
{
|
||||||
bool have_error;
|
|
||||||
int32 val;
|
int32 val;
|
||||||
|
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||||
|
|
||||||
val = numeric_int4_opt_error(jb->val.numeric, &have_error);
|
val = numeric_int4_safe(jb->val.numeric,
|
||||||
if (have_error)
|
(Node *) &escontext);
|
||||||
|
if (escontext.error_occurred)
|
||||||
RETURN_ERROR(ereport(ERROR,
|
RETURN_ERROR(ereport(ERROR,
|
||||||
(errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
|
(errcode(ERRCODE_NON_NUMERIC_SQL_JSON_ITEM),
|
||||||
errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
|
errmsg("argument \"%s\" of jsonpath item method .%s() is invalid for type %s",
|
||||||
@ -2149,11 +2151,11 @@ executeBinaryArithmExpr(JsonPathExecContext *cxt, JsonPathItem *jsp,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bool error = false;
|
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||||
|
|
||||||
res = func(lval->val.numeric, rval->val.numeric, &error);
|
res = func(lval->val.numeric, rval->val.numeric, (Node *) &escontext);
|
||||||
|
|
||||||
if (error)
|
if (escontext.error_occurred)
|
||||||
return jperError;
|
return jperError;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2433,7 +2435,7 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
|
|||||||
if (jsp->type != jpiDatetime && jsp->type != jpiDate &&
|
if (jsp->type != jpiDatetime && jsp->type != jpiDate &&
|
||||||
jsp->content.arg)
|
jsp->content.arg)
|
||||||
{
|
{
|
||||||
bool have_error;
|
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||||
|
|
||||||
jspGetArg(jsp, &elem);
|
jspGetArg(jsp, &elem);
|
||||||
|
|
||||||
@ -2441,9 +2443,9 @@ executeDateTimeMethod(JsonPathExecContext *cxt, JsonPathItem *jsp,
|
|||||||
elog(ERROR, "invalid jsonpath item type for %s argument",
|
elog(ERROR, "invalid jsonpath item type for %s argument",
|
||||||
jspOperationName(jsp->type));
|
jspOperationName(jsp->type));
|
||||||
|
|
||||||
time_precision = numeric_int4_opt_error(jspGetNumeric(&elem),
|
time_precision = numeric_int4_safe(jspGetNumeric(&elem),
|
||||||
&have_error);
|
(Node *) &escontext);
|
||||||
if (have_error)
|
if (escontext.error_occurred)
|
||||||
RETURN_ERROR(ereport(ERROR,
|
RETURN_ERROR(ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
|
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION),
|
||||||
errmsg("time precision of jsonpath item method .%s() is out of range for type integer",
|
errmsg("time precision of jsonpath item method .%s() is out of range for type integer",
|
||||||
@ -3462,7 +3464,7 @@ getArrayIndex(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
|
|||||||
JsonValueList found = {0};
|
JsonValueList found = {0};
|
||||||
JsonPathExecResult res = executeItem(cxt, jsp, jb, &found);
|
JsonPathExecResult res = executeItem(cxt, jsp, jb, &found);
|
||||||
Datum numeric_index;
|
Datum numeric_index;
|
||||||
bool have_error = false;
|
ErrorSaveContext escontext = {T_ErrorSaveContext};
|
||||||
|
|
||||||
if (jperIsError(res))
|
if (jperIsError(res))
|
||||||
return res;
|
return res;
|
||||||
@ -3477,10 +3479,10 @@ getArrayIndex(JsonPathExecContext *cxt, JsonPathItem *jsp, JsonbValue *jb,
|
|||||||
NumericGetDatum(jbv->val.numeric),
|
NumericGetDatum(jbv->val.numeric),
|
||||||
Int32GetDatum(0));
|
Int32GetDatum(0));
|
||||||
|
|
||||||
*index = numeric_int4_opt_error(DatumGetNumeric(numeric_index),
|
*index = numeric_int4_safe(DatumGetNumeric(numeric_index),
|
||||||
&have_error);
|
(Node *) &escontext);
|
||||||
|
|
||||||
if (have_error)
|
if (escontext.error_occurred)
|
||||||
RETURN_ERROR(ereport(ERROR,
|
RETURN_ERROR(ereport(ERROR,
|
||||||
(errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
|
(errcode(ERRCODE_INVALID_SQL_JSON_SUBSCRIPT),
|
||||||
errmsg("jsonpath array subscript is out of integer range"))));
|
errmsg("jsonpath array subscript is out of integer range"))));
|
||||||
|
@ -517,7 +517,7 @@ static void numericvar_deserialize(StringInfo buf, NumericVar *var);
|
|||||||
|
|
||||||
static Numeric duplicate_numeric(Numeric num);
|
static Numeric duplicate_numeric(Numeric num);
|
||||||
static Numeric make_result(const NumericVar *var);
|
static Numeric make_result(const NumericVar *var);
|
||||||
static Numeric make_result_opt_error(const NumericVar *var, bool *have_error);
|
static Numeric make_result_safe(const NumericVar *var, Node *escontext);
|
||||||
|
|
||||||
static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
|
static bool apply_typmod(NumericVar *var, int32 typmod, Node *escontext);
|
||||||
static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
|
static bool apply_typmod_special(Numeric num, int32 typmod, Node *escontext);
|
||||||
@ -717,7 +717,6 @@ numeric_in(PG_FUNCTION_ARGS)
|
|||||||
*/
|
*/
|
||||||
NumericVar value;
|
NumericVar value;
|
||||||
int base;
|
int base;
|
||||||
bool have_error;
|
|
||||||
|
|
||||||
init_var(&value);
|
init_var(&value);
|
||||||
|
|
||||||
@ -776,12 +775,7 @@ numeric_in(PG_FUNCTION_ARGS)
|
|||||||
if (!apply_typmod(&value, typmod, escontext))
|
if (!apply_typmod(&value, typmod, escontext))
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
|
|
||||||
res = make_result_opt_error(&value, &have_error);
|
res = make_result_safe(&value, escontext);
|
||||||
|
|
||||||
if (have_error)
|
|
||||||
ereturn(escontext, (Datum) 0,
|
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
|
||||||
errmsg("value overflows numeric format")));
|
|
||||||
|
|
||||||
free_var(&value);
|
free_var(&value);
|
||||||
}
|
}
|
||||||
@ -2874,20 +2868,18 @@ numeric_add(PG_FUNCTION_ARGS)
|
|||||||
Numeric num2 = PG_GETARG_NUMERIC(1);
|
Numeric num2 = PG_GETARG_NUMERIC(1);
|
||||||
Numeric res;
|
Numeric res;
|
||||||
|
|
||||||
res = numeric_add_opt_error(num1, num2, NULL);
|
res = numeric_add_safe(num1, num2, NULL);
|
||||||
|
|
||||||
PG_RETURN_NUMERIC(res);
|
PG_RETURN_NUMERIC(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* numeric_add_opt_error() -
|
* numeric_add_safe() -
|
||||||
*
|
*
|
||||||
* Internal version of numeric_add(). If "*have_error" flag is provided,
|
* Internal version of numeric_add() with support for soft error reporting.
|
||||||
* on error it's set to true, NULL returned. This is helpful when caller
|
|
||||||
* need to handle errors by itself.
|
|
||||||
*/
|
*/
|
||||||
Numeric
|
Numeric
|
||||||
numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
numeric_add_safe(Numeric num1, Numeric num2, Node *escontext)
|
||||||
{
|
{
|
||||||
NumericVar arg1;
|
NumericVar arg1;
|
||||||
NumericVar arg2;
|
NumericVar arg2;
|
||||||
@ -2931,7 +2923,7 @@ numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
|||||||
init_var(&result);
|
init_var(&result);
|
||||||
add_var(&arg1, &arg2, &result);
|
add_var(&arg1, &arg2, &result);
|
||||||
|
|
||||||
res = make_result_opt_error(&result, have_error);
|
res = make_result_safe(&result, escontext);
|
||||||
|
|
||||||
free_var(&result);
|
free_var(&result);
|
||||||
|
|
||||||
@ -2951,21 +2943,19 @@ numeric_sub(PG_FUNCTION_ARGS)
|
|||||||
Numeric num2 = PG_GETARG_NUMERIC(1);
|
Numeric num2 = PG_GETARG_NUMERIC(1);
|
||||||
Numeric res;
|
Numeric res;
|
||||||
|
|
||||||
res = numeric_sub_opt_error(num1, num2, NULL);
|
res = numeric_sub_safe(num1, num2, NULL);
|
||||||
|
|
||||||
PG_RETURN_NUMERIC(res);
|
PG_RETURN_NUMERIC(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* numeric_sub_opt_error() -
|
* numeric_sub_safe() -
|
||||||
*
|
*
|
||||||
* Internal version of numeric_sub(). If "*have_error" flag is provided,
|
* Internal version of numeric_sub() with support for soft error reporting.
|
||||||
* on error it's set to true, NULL returned. This is helpful when caller
|
|
||||||
* need to handle errors by itself.
|
|
||||||
*/
|
*/
|
||||||
Numeric
|
Numeric
|
||||||
numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext)
|
||||||
{
|
{
|
||||||
NumericVar arg1;
|
NumericVar arg1;
|
||||||
NumericVar arg2;
|
NumericVar arg2;
|
||||||
@ -3009,7 +2999,7 @@ numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
|||||||
init_var(&result);
|
init_var(&result);
|
||||||
sub_var(&arg1, &arg2, &result);
|
sub_var(&arg1, &arg2, &result);
|
||||||
|
|
||||||
res = make_result_opt_error(&result, have_error);
|
res = make_result_safe(&result, escontext);
|
||||||
|
|
||||||
free_var(&result);
|
free_var(&result);
|
||||||
|
|
||||||
@ -3029,21 +3019,19 @@ numeric_mul(PG_FUNCTION_ARGS)
|
|||||||
Numeric num2 = PG_GETARG_NUMERIC(1);
|
Numeric num2 = PG_GETARG_NUMERIC(1);
|
||||||
Numeric res;
|
Numeric res;
|
||||||
|
|
||||||
res = numeric_mul_opt_error(num1, num2, NULL);
|
res = numeric_mul_safe(num1, num2, NULL);
|
||||||
|
|
||||||
PG_RETURN_NUMERIC(res);
|
PG_RETURN_NUMERIC(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* numeric_mul_opt_error() -
|
* numeric_mul_safe() -
|
||||||
*
|
*
|
||||||
* Internal version of numeric_mul(). If "*have_error" flag is provided,
|
* Internal version of numeric_mul() with support for soft error reporting.
|
||||||
* on error it's set to true, NULL returned. This is helpful when caller
|
|
||||||
* need to handle errors by itself.
|
|
||||||
*/
|
*/
|
||||||
Numeric
|
Numeric
|
||||||
numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
numeric_mul_safe(Numeric num1, Numeric num2, Node *escontext)
|
||||||
{
|
{
|
||||||
NumericVar arg1;
|
NumericVar arg1;
|
||||||
NumericVar arg2;
|
NumericVar arg2;
|
||||||
@ -3130,7 +3118,7 @@ numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
|||||||
if (result.dscale > NUMERIC_DSCALE_MAX)
|
if (result.dscale > NUMERIC_DSCALE_MAX)
|
||||||
round_var(&result, NUMERIC_DSCALE_MAX);
|
round_var(&result, NUMERIC_DSCALE_MAX);
|
||||||
|
|
||||||
res = make_result_opt_error(&result, have_error);
|
res = make_result_safe(&result, escontext);
|
||||||
|
|
||||||
free_var(&result);
|
free_var(&result);
|
||||||
|
|
||||||
@ -3150,21 +3138,19 @@ numeric_div(PG_FUNCTION_ARGS)
|
|||||||
Numeric num2 = PG_GETARG_NUMERIC(1);
|
Numeric num2 = PG_GETARG_NUMERIC(1);
|
||||||
Numeric res;
|
Numeric res;
|
||||||
|
|
||||||
res = numeric_div_opt_error(num1, num2, NULL);
|
res = numeric_div_safe(num1, num2, NULL);
|
||||||
|
|
||||||
PG_RETURN_NUMERIC(res);
|
PG_RETURN_NUMERIC(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* numeric_div_opt_error() -
|
* numeric_div_safe() -
|
||||||
*
|
*
|
||||||
* Internal version of numeric_div(). If "*have_error" flag is provided,
|
* Internal version of numeric_div() with support for soft error reporting.
|
||||||
* on error it's set to true, NULL returned. This is helpful when caller
|
|
||||||
* need to handle errors by itself.
|
|
||||||
*/
|
*/
|
||||||
Numeric
|
Numeric
|
||||||
numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
numeric_div_safe(Numeric num1, Numeric num2, Node *escontext)
|
||||||
{
|
{
|
||||||
NumericVar arg1;
|
NumericVar arg1;
|
||||||
NumericVar arg2;
|
NumericVar arg2;
|
||||||
@ -3172,9 +3158,6 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
|||||||
Numeric res;
|
Numeric res;
|
||||||
int rscale;
|
int rscale;
|
||||||
|
|
||||||
if (have_error)
|
|
||||||
*have_error = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle NaN and infinities
|
* Handle NaN and infinities
|
||||||
*/
|
*/
|
||||||
@ -3189,15 +3172,7 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
|||||||
switch (numeric_sign_internal(num2))
|
switch (numeric_sign_internal(num2))
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if (have_error)
|
goto division_by_zero;
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
|
||||||
errmsg("division by zero")));
|
|
||||||
break;
|
|
||||||
case 1:
|
case 1:
|
||||||
return make_result(&const_pinf);
|
return make_result(&const_pinf);
|
||||||
case -1:
|
case -1:
|
||||||
@ -3212,15 +3187,7 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
|||||||
switch (numeric_sign_internal(num2))
|
switch (numeric_sign_internal(num2))
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
if (have_error)
|
goto division_by_zero;
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
|
||||||
errmsg("division by zero")));
|
|
||||||
break;
|
|
||||||
case 1:
|
case 1:
|
||||||
return make_result(&const_ninf);
|
return make_result(&const_ninf);
|
||||||
case -1:
|
case -1:
|
||||||
@ -3251,25 +3218,25 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
|||||||
*/
|
*/
|
||||||
rscale = select_div_scale(&arg1, &arg2);
|
rscale = select_div_scale(&arg1, &arg2);
|
||||||
|
|
||||||
/*
|
/* Check for division by zero */
|
||||||
* If "have_error" is provided, check for division by zero here
|
if (arg2.ndigits == 0 || arg2.digits[0] == 0)
|
||||||
*/
|
goto division_by_zero;
|
||||||
if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
|
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do the divide and return the result
|
* Do the divide and return the result
|
||||||
*/
|
*/
|
||||||
div_var(&arg1, &arg2, &result, rscale, true, true);
|
div_var(&arg1, &arg2, &result, rscale, true, true);
|
||||||
|
|
||||||
res = make_result_opt_error(&result, have_error);
|
res = make_result_safe(&result, escontext);
|
||||||
|
|
||||||
free_var(&result);
|
free_var(&result);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
division_by_zero:
|
||||||
|
ereturn(escontext, NULL,
|
||||||
|
errcode(ERRCODE_DIVISION_BY_ZERO),
|
||||||
|
errmsg("division by zero"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3374,30 +3341,25 @@ numeric_mod(PG_FUNCTION_ARGS)
|
|||||||
Numeric num2 = PG_GETARG_NUMERIC(1);
|
Numeric num2 = PG_GETARG_NUMERIC(1);
|
||||||
Numeric res;
|
Numeric res;
|
||||||
|
|
||||||
res = numeric_mod_opt_error(num1, num2, NULL);
|
res = numeric_mod_safe(num1, num2, NULL);
|
||||||
|
|
||||||
PG_RETURN_NUMERIC(res);
|
PG_RETURN_NUMERIC(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* numeric_mod_opt_error() -
|
* numeric_mod_safe() -
|
||||||
*
|
*
|
||||||
* Internal version of numeric_mod(). If "*have_error" flag is provided,
|
* Internal version of numeric_mod() with support for soft error reporting.
|
||||||
* on error it's set to true, NULL returned. This is helpful when caller
|
|
||||||
* need to handle errors by itself.
|
|
||||||
*/
|
*/
|
||||||
Numeric
|
Numeric
|
||||||
numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext)
|
||||||
{
|
{
|
||||||
Numeric res;
|
Numeric res;
|
||||||
NumericVar arg1;
|
NumericVar arg1;
|
||||||
NumericVar arg2;
|
NumericVar arg2;
|
||||||
NumericVar result;
|
NumericVar result;
|
||||||
|
|
||||||
if (have_error)
|
|
||||||
*have_error = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle NaN and infinities. We follow POSIX fmod() on this, except that
|
* Handle NaN and infinities. We follow POSIX fmod() on this, except that
|
||||||
* POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
|
* POSIX treats x-is-infinite and y-is-zero identically, raising EDOM and
|
||||||
@ -3410,16 +3372,8 @@ numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
|||||||
if (NUMERIC_IS_INF(num1))
|
if (NUMERIC_IS_INF(num1))
|
||||||
{
|
{
|
||||||
if (numeric_sign_internal(num2) == 0)
|
if (numeric_sign_internal(num2) == 0)
|
||||||
{
|
goto division_by_zero;
|
||||||
if (have_error)
|
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_DIVISION_BY_ZERO),
|
|
||||||
errmsg("division by zero")));
|
|
||||||
}
|
|
||||||
/* Inf % any nonzero = NaN */
|
/* Inf % any nonzero = NaN */
|
||||||
return make_result(&const_nan);
|
return make_result(&const_nan);
|
||||||
}
|
}
|
||||||
@ -3432,22 +3386,22 @@ numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
|
|||||||
|
|
||||||
init_var(&result);
|
init_var(&result);
|
||||||
|
|
||||||
/*
|
/* Check for division by zero */
|
||||||
* If "have_error" is provided, check for division by zero here
|
if (arg2.ndigits == 0 || arg2.digits[0] == 0)
|
||||||
*/
|
goto division_by_zero;
|
||||||
if (have_error && (arg2.ndigits == 0 || arg2.digits[0] == 0))
|
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mod_var(&arg1, &arg2, &result);
|
mod_var(&arg1, &arg2, &result);
|
||||||
|
|
||||||
res = make_result_opt_error(&result, NULL);
|
res = make_result_safe(&result, escontext);
|
||||||
|
|
||||||
free_var(&result);
|
free_var(&result);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
division_by_zero:
|
||||||
|
ereturn(escontext, NULL,
|
||||||
|
errcode(ERRCODE_DIVISION_BY_ZERO),
|
||||||
|
errmsg("division by zero"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -4404,52 +4358,34 @@ int4_numeric(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_NUMERIC(int64_to_numeric(val));
|
PG_RETURN_NUMERIC(int64_to_numeric(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal version of int4_numeric() with support for soft error reporting.
|
||||||
|
*/
|
||||||
int32
|
int32
|
||||||
numeric_int4_opt_error(Numeric num, bool *have_error)
|
numeric_int4_safe(Numeric num, Node *escontext)
|
||||||
{
|
{
|
||||||
NumericVar x;
|
NumericVar x;
|
||||||
int32 result;
|
int32 result;
|
||||||
|
|
||||||
if (have_error)
|
|
||||||
*have_error = false;
|
|
||||||
|
|
||||||
if (NUMERIC_IS_SPECIAL(num))
|
if (NUMERIC_IS_SPECIAL(num))
|
||||||
{
|
|
||||||
if (have_error)
|
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (NUMERIC_IS_NAN(num))
|
if (NUMERIC_IS_NAN(num))
|
||||||
ereport(ERROR,
|
ereturn(escontext, 0,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("cannot convert NaN to %s", "integer")));
|
errmsg("cannot convert NaN to %s", "integer")));
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereturn(escontext, 0,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("cannot convert infinity to %s", "integer")));
|
errmsg("cannot convert infinity to %s", "integer")));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert to variable format, then convert to int4 */
|
/* Convert to variable format, then convert to int4 */
|
||||||
init_var_from_num(num, &x);
|
init_var_from_num(num, &x);
|
||||||
|
|
||||||
if (!numericvar_to_int32(&x, &result))
|
if (!numericvar_to_int32(&x, &result))
|
||||||
{
|
ereturn(escontext, 0,
|
||||||
if (have_error)
|
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("integer out of range")));
|
errmsg("integer out of range")));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -4459,7 +4395,7 @@ numeric_int4(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
Numeric num = PG_GETARG_NUMERIC(0);
|
Numeric num = PG_GETARG_NUMERIC(0);
|
||||||
|
|
||||||
PG_RETURN_INT32(numeric_int4_opt_error(num, NULL));
|
PG_RETURN_INT32(numeric_int4_safe(num, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4492,52 +4428,34 @@ int8_numeric(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_NUMERIC(int64_to_numeric(val));
|
PG_RETURN_NUMERIC(int64_to_numeric(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal version of int8_numeric() with support for soft error reporting.
|
||||||
|
*/
|
||||||
int64
|
int64
|
||||||
numeric_int8_opt_error(Numeric num, bool *have_error)
|
numeric_int8_safe(Numeric num, Node *escontext)
|
||||||
{
|
{
|
||||||
NumericVar x;
|
NumericVar x;
|
||||||
int64 result;
|
int64 result;
|
||||||
|
|
||||||
if (have_error)
|
|
||||||
*have_error = false;
|
|
||||||
|
|
||||||
if (NUMERIC_IS_SPECIAL(num))
|
if (NUMERIC_IS_SPECIAL(num))
|
||||||
{
|
|
||||||
if (have_error)
|
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (NUMERIC_IS_NAN(num))
|
if (NUMERIC_IS_NAN(num))
|
||||||
ereport(ERROR,
|
ereturn(escontext, 0,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("cannot convert NaN to %s", "bigint")));
|
errmsg("cannot convert NaN to %s", "bigint")));
|
||||||
else
|
else
|
||||||
ereport(ERROR,
|
ereturn(escontext, 0,
|
||||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||||
errmsg("cannot convert infinity to %s", "bigint")));
|
errmsg("cannot convert infinity to %s", "bigint")));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert to variable format, then convert to int8 */
|
/* Convert to variable format, then convert to int8 */
|
||||||
init_var_from_num(num, &x);
|
init_var_from_num(num, &x);
|
||||||
|
|
||||||
if (!numericvar_to_int64(&x, &result))
|
if (!numericvar_to_int64(&x, &result))
|
||||||
{
|
ereturn(escontext, 0,
|
||||||
if (have_error)
|
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("bigint out of range")));
|
errmsg("bigint out of range")));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -4547,7 +4465,7 @@ numeric_int8(PG_FUNCTION_ARGS)
|
|||||||
{
|
{
|
||||||
Numeric num = PG_GETARG_NUMERIC(0);
|
Numeric num = PG_GETARG_NUMERIC(0);
|
||||||
|
|
||||||
PG_RETURN_INT64(numeric_int8_opt_error(num, NULL));
|
PG_RETURN_INT64(numeric_int8_safe(num, NULL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7583,16 +7501,13 @@ duplicate_numeric(Numeric num)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make_result_opt_error() -
|
* make_result_safe() -
|
||||||
*
|
*
|
||||||
* Create the packed db numeric format in palloc()'d memory from
|
* Create the packed db numeric format in palloc()'d memory from
|
||||||
* a variable. This will handle NaN and Infinity cases.
|
* a variable. This will handle NaN and Infinity cases.
|
||||||
*
|
|
||||||
* If "have_error" isn't NULL, on overflow *have_error is set to true and
|
|
||||||
* NULL is returned. This is helpful when caller needs to handle errors.
|
|
||||||
*/
|
*/
|
||||||
static Numeric
|
static Numeric
|
||||||
make_result_opt_error(const NumericVar *var, bool *have_error)
|
make_result_safe(const NumericVar *var, Node *escontext)
|
||||||
{
|
{
|
||||||
Numeric result;
|
Numeric result;
|
||||||
NumericDigit *digits = var->digits;
|
NumericDigit *digits = var->digits;
|
||||||
@ -7601,9 +7516,6 @@ make_result_opt_error(const NumericVar *var, bool *have_error)
|
|||||||
int n;
|
int n;
|
||||||
Size len;
|
Size len;
|
||||||
|
|
||||||
if (have_error)
|
|
||||||
*have_error = false;
|
|
||||||
|
|
||||||
if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
|
if ((sign & NUMERIC_SIGN_MASK) == NUMERIC_SPECIAL)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -7676,19 +7588,9 @@ make_result_opt_error(const NumericVar *var, bool *have_error)
|
|||||||
/* Check for overflow of int16 fields */
|
/* Check for overflow of int16 fields */
|
||||||
if (NUMERIC_WEIGHT(result) != weight ||
|
if (NUMERIC_WEIGHT(result) != weight ||
|
||||||
NUMERIC_DSCALE(result) != var->dscale)
|
NUMERIC_DSCALE(result) != var->dscale)
|
||||||
{
|
ereturn(escontext, NULL,
|
||||||
if (have_error)
|
|
||||||
{
|
|
||||||
*have_error = true;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ereport(ERROR,
|
|
||||||
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
|
||||||
errmsg("value overflows numeric format")));
|
errmsg("value overflows numeric format")));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_numeric("make_result()", result);
|
dump_numeric("make_result()", result);
|
||||||
return result;
|
return result;
|
||||||
@ -7698,12 +7600,12 @@ make_result_opt_error(const NumericVar *var, bool *have_error)
|
|||||||
/*
|
/*
|
||||||
* make_result() -
|
* make_result() -
|
||||||
*
|
*
|
||||||
* An interface to make_result_opt_error() without "have_error" argument.
|
* An interface to make_result_safe() without "escontext" argument.
|
||||||
*/
|
*/
|
||||||
static Numeric
|
static Numeric
|
||||||
make_result(const NumericVar *var)
|
make_result(const NumericVar *var)
|
||||||
{
|
{
|
||||||
return make_result_opt_error(var, NULL);
|
return make_result_safe(var, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5629,8 +5629,8 @@ timestamp_part_common(PG_FUNCTION_ARGS, bool retnumeric)
|
|||||||
|
|
||||||
case DTK_JULIAN:
|
case DTK_JULIAN:
|
||||||
if (retnumeric)
|
if (retnumeric)
|
||||||
PG_RETURN_NUMERIC(numeric_add_opt_error(int64_to_numeric(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)),
|
PG_RETURN_NUMERIC(numeric_add_safe(int64_to_numeric(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)),
|
||||||
numeric_div_opt_error(int64_to_numeric(((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) * INT64CONST(1000000) + fsec),
|
numeric_div_safe(int64_to_numeric(((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) * INT64CONST(1000000) + fsec),
|
||||||
int64_to_numeric(SECS_PER_DAY * INT64CONST(1000000)),
|
int64_to_numeric(SECS_PER_DAY * INT64CONST(1000000)),
|
||||||
NULL),
|
NULL),
|
||||||
NULL));
|
NULL));
|
||||||
@ -5685,7 +5685,7 @@ timestamp_part_common(PG_FUNCTION_ARGS, bool retnumeric)
|
|||||||
result = int64_div_fast_to_numeric(timestamp - epoch, 6);
|
result = int64_div_fast_to_numeric(timestamp - epoch, 6);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = numeric_div_opt_error(numeric_sub_opt_error(int64_to_numeric(timestamp),
|
result = numeric_div_safe(numeric_sub_safe(int64_to_numeric(timestamp),
|
||||||
int64_to_numeric(epoch),
|
int64_to_numeric(epoch),
|
||||||
NULL),
|
NULL),
|
||||||
int64_to_numeric(1000000),
|
int64_to_numeric(1000000),
|
||||||
@ -5903,8 +5903,8 @@ timestamptz_part_common(PG_FUNCTION_ARGS, bool retnumeric)
|
|||||||
|
|
||||||
case DTK_JULIAN:
|
case DTK_JULIAN:
|
||||||
if (retnumeric)
|
if (retnumeric)
|
||||||
PG_RETURN_NUMERIC(numeric_add_opt_error(int64_to_numeric(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)),
|
PG_RETURN_NUMERIC(numeric_add_safe(int64_to_numeric(date2j(tm->tm_year, tm->tm_mon, tm->tm_mday)),
|
||||||
numeric_div_opt_error(int64_to_numeric(((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) * INT64CONST(1000000) + fsec),
|
numeric_div_safe(int64_to_numeric(((((tm->tm_hour * MINS_PER_HOUR) + tm->tm_min) * SECS_PER_MINUTE) + tm->tm_sec) * INT64CONST(1000000) + fsec),
|
||||||
int64_to_numeric(SECS_PER_DAY * INT64CONST(1000000)),
|
int64_to_numeric(SECS_PER_DAY * INT64CONST(1000000)),
|
||||||
NULL),
|
NULL),
|
||||||
NULL));
|
NULL));
|
||||||
@ -5956,7 +5956,7 @@ timestamptz_part_common(PG_FUNCTION_ARGS, bool retnumeric)
|
|||||||
result = int64_div_fast_to_numeric(timestamp - epoch, 6);
|
result = int64_div_fast_to_numeric(timestamp - epoch, 6);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = numeric_div_opt_error(numeric_sub_opt_error(int64_to_numeric(timestamp),
|
result = numeric_div_safe(numeric_sub_safe(int64_to_numeric(timestamp),
|
||||||
int64_to_numeric(epoch),
|
int64_to_numeric(epoch),
|
||||||
NULL),
|
NULL),
|
||||||
int64_to_numeric(1000000),
|
int64_to_numeric(1000000),
|
||||||
@ -6247,7 +6247,7 @@ interval_part_common(PG_FUNCTION_ARGS, bool retnumeric)
|
|||||||
result = int64_div_fast_to_numeric(val, 6);
|
result = int64_div_fast_to_numeric(val, 6);
|
||||||
else
|
else
|
||||||
result =
|
result =
|
||||||
numeric_add_opt_error(int64_div_fast_to_numeric(interval->time, 6),
|
numeric_add_safe(int64_div_fast_to_numeric(interval->time, 6),
|
||||||
int64_to_numeric(secs_from_day_month),
|
int64_to_numeric(secs_from_day_month),
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#include "common/pg_prng.h"
|
#include "common/pg_prng.h"
|
||||||
#include "fmgr.h"
|
#include "fmgr.h"
|
||||||
|
|
||||||
|
/* forward declaration to avoid node.h include */
|
||||||
|
typedef struct Node Node;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Limits on the precision and scale specifiable in a NUMERIC typmod. The
|
* Limits on the precision and scale specifiable in a NUMERIC typmod. The
|
||||||
* precision is strictly positive, but the scale may be positive or negative.
|
* precision is strictly positive, but the scale may be positive or negative.
|
||||||
@ -91,18 +94,13 @@ extern char *numeric_normalize(Numeric num);
|
|||||||
extern Numeric int64_to_numeric(int64 val);
|
extern Numeric int64_to_numeric(int64 val);
|
||||||
extern Numeric int64_div_fast_to_numeric(int64 val1, int log10val2);
|
extern Numeric int64_div_fast_to_numeric(int64 val1, int log10val2);
|
||||||
|
|
||||||
extern Numeric numeric_add_opt_error(Numeric num1, Numeric num2,
|
extern Numeric numeric_add_safe(Numeric num1, Numeric num2, Node *escontext);
|
||||||
bool *have_error);
|
extern Numeric numeric_sub_safe(Numeric num1, Numeric num2, Node *escontext);
|
||||||
extern Numeric numeric_sub_opt_error(Numeric num1, Numeric num2,
|
extern Numeric numeric_mul_safe(Numeric num1, Numeric num2, Node *escontext);
|
||||||
bool *have_error);
|
extern Numeric numeric_div_safe(Numeric num1, Numeric num2, Node *escontext);
|
||||||
extern Numeric numeric_mul_opt_error(Numeric num1, Numeric num2,
|
extern Numeric numeric_mod_safe(Numeric num1, Numeric num2, Node *escontext);
|
||||||
bool *have_error);
|
extern int32 numeric_int4_safe(Numeric num, Node *escontext);
|
||||||
extern Numeric numeric_div_opt_error(Numeric num1, Numeric num2,
|
extern int64 numeric_int8_safe(Numeric num, Node *escontext);
|
||||||
bool *have_error);
|
|
||||||
extern Numeric numeric_mod_opt_error(Numeric num1, Numeric num2,
|
|
||||||
bool *have_error);
|
|
||||||
extern int32 numeric_int4_opt_error(Numeric num, bool *have_error);
|
|
||||||
extern int64 numeric_int8_opt_error(Numeric num, bool *have_error);
|
|
||||||
|
|
||||||
extern Numeric random_numeric(pg_prng_state *state,
|
extern Numeric random_numeric(pg_prng_state *state,
|
||||||
Numeric rmin, Numeric rmax);
|
Numeric rmin, Numeric rmax);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user