@ -517,7 +517,7 @@ static void numericvar_deserialize(StringInfo buf, NumericVar *var);
static Numeric duplicate_numeric ( Numeric num ) ;
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_special ( Numeric num , int32 typmod , Node * escontext ) ;
@ -717,7 +717,6 @@ numeric_in(PG_FUNCTION_ARGS)
*/
NumericVar value ;
int base ;
bool have_error ;
init_var ( & value ) ;
@ -776,12 +775,7 @@ numeric_in(PG_FUNCTION_ARGS)
if ( ! apply_typmod ( & value , typmod , escontext ) )
PG_RETURN_NULL ( ) ;
res = make_result_opt_error ( & value , & have_error ) ;
if ( have_error )
ereturn ( escontext , ( Datum ) 0 ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value overflows numeric format " ) ) ) ;
res = make_result_safe ( & value , escontext ) ;
free_var ( & value ) ;
}
@ -2874,20 +2868,18 @@ numeric_add(PG_FUNCTION_ARGS)
Numeric num2 = PG_GETARG_NUMERIC ( 1 ) ;
Numeric res ;
res = numeric_add_opt_error ( num1 , num2 , NULL ) ;
res = numeric_add_safe ( num1 , num2 , NULL ) ;
PG_RETURN_NUMERIC ( res ) ;
}
/*
* numeric_add_opt_error ( ) -
* numeric_add_safe ( ) -
*
* Internal version of numeric_add ( ) . If " *have_error " flag is provided ,
* on error it ' s set to true , NULL returned . This is helpful when caller
* need to handle errors by itself .
* Internal version of numeric_add ( ) with support for soft error reporting .
*/
Numeric
numeric_add_opt_error ( Numeric num1 , Numeric num2 , bool * have_error )
numeric_add_safe ( Numeric num1 , Numeric num2 , Node * escontext )
{
NumericVar arg1 ;
NumericVar arg2 ;
@ -2931,7 +2923,7 @@ numeric_add_opt_error(Numeric num1, Numeric num2, bool *have_error)
init_var ( & result ) ;
add_var ( & arg1 , & arg2 , & result ) ;
res = make_result_opt_error ( & result , have_error ) ;
res = make_result_safe ( & result , escontext ) ;
free_var ( & result ) ;
@ -2951,21 +2943,19 @@ numeric_sub(PG_FUNCTION_ARGS)
Numeric num2 = PG_GETARG_NUMERIC ( 1 ) ;
Numeric res ;
res = numeric_sub_opt_error ( num1 , num2 , NULL ) ;
res = numeric_sub_safe ( num1 , num2 , NULL ) ;
PG_RETURN_NUMERIC ( res ) ;
}
/*
* numeric_sub_opt_error ( ) -
* numeric_sub_safe ( ) -
*
* Internal version of numeric_sub ( ) . If " *have_error " flag is provided ,
* on error it ' s set to true , NULL returned . This is helpful when caller
* need to handle errors by itself .
* Internal version of numeric_sub ( ) with support for soft error reporting .
*/
Numeric
numeric_sub_opt_error ( Numeric num1 , Numeric num2 , bool * have_error )
numeric_sub_safe ( Numeric num1 , Numeric num2 , Node * escontext )
{
NumericVar arg1 ;
NumericVar arg2 ;
@ -3009,7 +2999,7 @@ numeric_sub_opt_error(Numeric num1, Numeric num2, bool *have_error)
init_var ( & result ) ;
sub_var ( & arg1 , & arg2 , & result ) ;
res = make_result_opt_error ( & result , have_error ) ;
res = make_result_safe ( & result , escontext ) ;
free_var ( & result ) ;
@ -3029,21 +3019,19 @@ numeric_mul(PG_FUNCTION_ARGS)
Numeric num2 = PG_GETARG_NUMERIC ( 1 ) ;
Numeric res ;
res = numeric_mul_opt_error ( num1 , num2 , NULL ) ;
res = numeric_mul_safe ( num1 , num2 , NULL ) ;
PG_RETURN_NUMERIC ( res ) ;
}
/*
* numeric_mul_opt_error ( ) -
* numeric_mul_safe ( ) -
*
* Internal version of numeric_mul ( ) . If " *have_error " flag is provided ,
* on error it ' s set to true , NULL returned . This is helpful when caller
* need to handle errors by itself .
* Internal version of numeric_mul ( ) with support for soft error reporting .
*/
Numeric
numeric_mul_opt_error ( Numeric num1 , Numeric num2 , bool * have_error )
numeric_mul_safe ( Numeric num1 , Numeric num2 , Node * escontext )
{
NumericVar arg1 ;
NumericVar arg2 ;
@ -3130,7 +3118,7 @@ numeric_mul_opt_error(Numeric num1, Numeric num2, bool *have_error)
if ( result . dscale > 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 ) ;
@ -3150,21 +3138,19 @@ numeric_div(PG_FUNCTION_ARGS)
Numeric num2 = PG_GETARG_NUMERIC ( 1 ) ;
Numeric res ;
res = numeric_div_opt_error ( num1 , num2 , NULL ) ;
res = numeric_div_safe ( num1 , num2 , NULL ) ;
PG_RETURN_NUMERIC ( res ) ;
}
/*
* numeric_div_opt_error ( ) -
* numeric_div_safe ( ) -
*
* Internal version of numeric_div ( ) . If " *have_error " flag is provided ,
* on error it ' s set to true , NULL returned . This is helpful when caller
* need to handle errors by itself .
* Internal version of numeric_div ( ) with support for soft error reporting .
*/
Numeric
numeric_div_opt_error ( Numeric num1 , Numeric num2 , bool * have_error )
numeric_div_safe ( Numeric num1 , Numeric num2 , Node * escontext )
{
NumericVar arg1 ;
NumericVar arg2 ;
@ -3172,9 +3158,6 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
Numeric res ;
int rscale ;
if ( have_error )
* have_error = false ;
/*
* Handle NaN and infinities
*/
@ -3189,15 +3172,7 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
switch ( numeric_sign_internal ( num2 ) )
{
case 0 :
if ( have_error )
{
* have_error = true ;
return NULL ;
}
ereport ( ERROR ,
( errcode ( ERRCODE_DIVISION_BY_ZERO ) ,
errmsg ( " division by zero " ) ) ) ;
break ;
goto division_by_zero ;
case 1 :
return make_result ( & const_pinf ) ;
case - 1 :
@ -3212,15 +3187,7 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
switch ( numeric_sign_internal ( num2 ) )
{
case 0 :
if ( have_error )
{
* have_error = true ;
return NULL ;
}
ereport ( ERROR ,
( errcode ( ERRCODE_DIVISION_BY_ZERO ) ,
errmsg ( " division by zero " ) ) ) ;
break ;
goto division_by_zero ;
case 1 :
return make_result ( & const_ninf ) ;
case - 1 :
@ -3251,25 +3218,25 @@ numeric_div_opt_error(Numeric num1, Numeric num2, bool *have_error)
*/
rscale = select_div_scale ( & arg1 , & arg2 ) ;
/*
* If " have_error " is provided , check for division by zero here
*/
if ( have_error & & ( arg2 . ndigits = = 0 | | arg2 . digits [ 0 ] = = 0 ) )
{
* have_error = true ;
return NULL ;
}
/* Check for division by zero */
if ( arg2 . ndigits = = 0 | | arg2 . digits [ 0 ] = = 0 )
goto division_by_zero ;
/*
* Do the divide and return the result
*/
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 ) ;
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 res ;
res = numeric_mod_opt_error ( num1 , num2 , NULL ) ;
res = numeric_mod_safe ( num1 , num2 , NULL ) ;
PG_RETURN_NUMERIC ( res ) ;
}
/*
* numeric_mod_opt_error ( ) -
* numeric_mod_safe ( ) -
*
* Internal version of numeric_mod ( ) . If " *have_error " flag is provided ,
* on error it ' s set to true , NULL returned . This is helpful when caller
* need to handle errors by itself .
* Internal version of numeric_mod ( ) with support for soft error reporting .
*/
Numeric
numeric_mod_opt_error ( Numeric num1 , Numeric num2 , bool * have_error )
numeric_mod_safe ( Numeric num1 , Numeric num2 , Node * escontext )
{
Numeric res ;
NumericVar arg1 ;
NumericVar arg2 ;
NumericVar result ;
if ( have_error )
* have_error = false ;
/*
* 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
@ -3410,16 +3372,8 @@ numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
if ( NUMERIC_IS_INF ( num1 ) )
{
if ( numeric_sign_internal ( num2 ) = = 0 )
{
if ( have_error )
{
* have_error = true ;
return NULL ;
}
ereport ( ERROR ,
( errcode ( ERRCODE_DIVISION_BY_ZERO ) ,
errmsg ( " division by zero " ) ) ) ;
}
goto division_by_zero ;
/* Inf % any nonzero = NaN */
return make_result ( & const_nan ) ;
}
@ -3432,22 +3386,22 @@ numeric_mod_opt_error(Numeric num1, Numeric num2, bool *have_error)
init_var ( & result ) ;
/*
* If " have_error " is provided , check for division by zero here
*/
if ( have_error & & ( arg2 . ndigits = = 0 | | arg2 . digits [ 0 ] = = 0 ) )
{
* have_error = true ;
return NULL ;
}
/* Check for division by zero */
if ( arg2 . ndigits = = 0 | | arg2 . digits [ 0 ] = = 0 )
goto division_by_zero ;
mod_var ( & arg1 , & arg2 , & result ) ;
res = make_result_opt_error ( & result , NULL ) ;
res = make_result_safe ( & result , escontext ) ;
free_var ( & result ) ;
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 ) ) ;
}
/*
* Internal version of int4_numeric ( ) with support for soft error reporting .
*/
int32
numeric_int4_opt_error ( Numeric num , bool * have_error )
numeric_int4_safe ( Numeric num , Node * escontext )
{
NumericVar x ;
int32 result ;
if ( have_error )
* have_error = false ;
if ( NUMERIC_IS_SPECIAL ( num ) )
{
if ( have_error )
{
* have_error = true ;
return 0 ;
}
if ( NUMERIC_IS_NAN ( num ) )
ereturn ( escontext , 0 ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot convert NaN to %s " , " integer " ) ) ) ;
else
{
if ( NUMERIC_IS_NAN ( num ) )
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot convert NaN to %s " , " integer " ) ) ) ;
else
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot convert infinity to %s " , " integer " ) ) ) ;
}
ereturn ( escontext , 0 ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot convert infinity to %s " , " integer " ) ) ) ;
}
/* Convert to variable format, then convert to int4 */
init_var_from_num ( num , & x ) ;
if ( ! numericvar_to_int32 ( & x , & result ) )
{
if ( have_error )
{
* have_error = true ;
return 0 ;
}
else
{
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " integer out of range " ) ) ) ;
}
}
ereturn ( escontext , 0 ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " integer out of range " ) ) ) ;
return result ;
}
@ -4459,7 +4395,7 @@ numeric_int4(PG_FUNCTION_ARGS)
{
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 ) ) ;
}
/*
* Internal version of int8_numeric ( ) with support for soft error reporting .
*/
int64
numeric_int8_opt_error ( Numeric num , bool * have_error )
numeric_int8_safe ( Numeric num , Node * escontext )
{
NumericVar x ;
int64 result ;
if ( have_error )
* have_error = false ;
if ( NUMERIC_IS_SPECIAL ( num ) )
{
if ( have_error )
{
* have_error = true ;
return 0 ;
}
if ( NUMERIC_IS_NAN ( num ) )
ereturn ( escontext , 0 ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot convert NaN to %s " , " bigint " ) ) ) ;
else
{
if ( NUMERIC_IS_NAN ( num ) )
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot convert NaN to %s " , " bigint " ) ) ) ;
else
ereport ( ERROR ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot convert infinity to %s " , " bigint " ) ) ) ;
}
ereturn ( escontext , 0 ,
( errcode ( ERRCODE_FEATURE_NOT_SUPPORTED ) ,
errmsg ( " cannot convert infinity to %s " , " bigint " ) ) ) ;
}
/* Convert to variable format, then convert to int8 */
init_var_from_num ( num , & x ) ;
if ( ! numericvar_to_int64 ( & x , & result ) )
{
if ( have_error )
{
* have_error = true ;
return 0 ;
}
else
{
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " bigint out of range " ) ) ) ;
}
}
ereturn ( escontext , 0 ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " bigint out of range " ) ) ) ;
return result ;
}
@ -4547,7 +4465,7 @@ numeric_int8(PG_FUNCTION_ARGS)
{
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
* 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
make_result_opt_error ( const NumericVar * var , bool * have_error )
make_result_safe ( const NumericVar * var , Node * escontext )
{
Numeric result ;
NumericDigit * digits = var - > digits ;
@ -7601,9 +7516,6 @@ make_result_opt_error(const NumericVar *var, bool *have_error)
int n ;
Size len ;
if ( have_error )
* have_error = false ;
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 */
if ( NUMERIC_WEIGHT ( result ) ! = weight | |
NUMERIC_DSCALE ( result ) ! = var - > dscale )
{
if ( have_error )
{
* have_error = true ;
return NULL ;
}
else
{
ereport ( ERROR ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value overflows numeric format " ) ) ) ;
}
}
ereturn ( escontext , NULL ,
( errcode ( ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ) ,
errmsg ( " value overflows numeric format " ) ) ) ;
dump_numeric ( " make_result() " , result ) ;
return result ;
@ -7698,12 +7600,12 @@ make_result_opt_error(const NumericVar *var, bool *have_error)
/*
* make_result ( ) -
*
* An interface to make_result_opt_error ( ) without " have_error " argument .
* An interface to make_result_safe ( ) without " escontext " argument .
*/
static Numeric
make_result ( const NumericVar * var )
{
return make_result_opt_error ( var , NULL ) ;
return make_result_safe ( var , NULL ) ;
}