2222#include "funcapi.h"
2323#include "libpq/pqformat.h"
2424#include "access/hash.h"
25+ #include "common/int.h"
2526#include "utils/array.h"
2627#include "utils/builtins.h"
2728
2829#include "utils/int8.h"
2930
3031#include "utils/numeric.h"
3132
32- #define MAXINT8LEN 25
33+ #define FIXEDDECIMAL_INT64STRLEN 25
3334
3435/*
3536 * The scale which the number is actually stored.
@@ -681,7 +682,7 @@ Datum
681682fixeddecimalout (PG_FUNCTION_ARGS )
682683{
683684 int64 val = PG_GETARG_INT64 (0 );
684- char buf [MAXINT8LEN + 1 ];
685+ char buf [FIXEDDECIMAL_INT64STRLEN + 1 ];
685686 char * end = fixeddecimal2str (val , buf );
686687 PG_RETURN_CSTRING (pnstrdup (buf , end - buf ));
687688}
@@ -1258,21 +1259,11 @@ fixeddecimalum(PG_FUNCTION_ARGS)
12581259 int64 arg = PG_GETARG_INT64 (0 );
12591260 int64 result ;
12601261
1261- #ifdef HAVE_BUILTIN_OVERFLOW
1262- int64 zero = 0 ;
1263-
1264- if (__builtin_sub_overflow (zero , arg , & result ))
1265- ereport (ERROR ,
1266- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
1267- errmsg ("fixeddecimal out of range" )));
1268- #else
1269- result = - arg ;
1270- /* overflow check (needed for INT64_MIN) */
1271- if (arg != 0 && SAMESIGN (result , arg ))
1262+ if (pg_sub_s64_overflow (0 , arg , & result ))
12721263 ereport (ERROR ,
12731264 (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
12741265 errmsg ("fixeddecimal out of range" )));
1275- #endif /* HAVE_BUILTIN_OVERFLOW */
1266+
12761267 PG_RETURN_INT64 (result );
12771268}
12781269
@@ -1291,24 +1282,10 @@ fixeddecimalpl(PG_FUNCTION_ARGS)
12911282 int64 arg2 = PG_GETARG_INT64 (1 );
12921283 int64 result ;
12931284
1294- #ifdef HAVE_BUILTIN_OVERFLOW
1295- if (__builtin_add_overflow (arg1 , arg2 , & result ))
1285+ if (pg_add_s64_overflow (arg1 , arg2 , & result ))
12961286 ereport (ERROR ,
12971287 (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
12981288 errmsg ("fixeddecimal out of range" )));
1299- #else
1300- result = arg1 + arg2 ;
1301-
1302- /*
1303- * Overflow check. If the inputs are of different signs then their sum
1304- * cannot overflow. If the inputs are of the same sign, their sum had
1305- * better be that sign too.
1306- */
1307- if (SAMESIGN (arg1 , arg2 ) && !SAMESIGN (result , arg1 ))
1308- ereport (ERROR ,
1309- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
1310- errmsg ("fixeddecimal out of range" )));
1311- #endif /* HAVE_BUILTIN_OVERFLOW */
13121289
13131290 PG_RETURN_INT64 (result );
13141291}
@@ -1320,24 +1297,10 @@ fixeddecimalmi(PG_FUNCTION_ARGS)
13201297 int64 arg2 = PG_GETARG_INT64 (1 );
13211298 int64 result ;
13221299
1323- #ifdef HAVE_BUILTIN_OVERFLOW
1324- if (__builtin_sub_overflow (arg1 , arg2 , & result ))
1300+ if (pg_sub_s64_overflow (arg1 , arg2 , & result ))
13251301 ereport (ERROR ,
13261302 (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
13271303 errmsg ("fixeddecimal out of range" )));
1328- #else
1329- result = arg1 - arg2 ;
1330-
1331- /*
1332- * Overflow check. If the inputs are of the same sign then their
1333- * difference cannot overflow. If they are of different signs then the
1334- * result should be of the same sign as the first input.
1335- */
1336- if (!SAMESIGN (arg1 , arg2 ) && !SAMESIGN (result , arg1 ))
1337- ereport (ERROR ,
1338- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
1339- errmsg ("fixeddecimal out of range" )));
1340- #endif /* HAVE_BUILTIN_OVERFLOW */
13411304
13421305 PG_RETURN_INT64 (result );
13431306}
@@ -2163,18 +2126,11 @@ makeFixedDecimalAggState(FunctionCallInfo fcinfo)
21632126static void
21642127fixeddecimal_accum (FixedDecimalAggState * state , int64 newval )
21652128{
2166- #ifdef HAVE_BUILTIN_OVERFLOW
2167- if (__builtin_add_overflow (state -> sumX , newval , & state -> sumX ))
2168- ereport (ERROR ,
2169- (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
2170- errmsg ("fixeddecimal out of range" )));
2171- state -> N ++ ;
2172- #else
21732129 if (state -> N ++ > 0 )
21742130 {
2175- int64 result = state -> sumX + newval ;
2131+ int64 result ;
21762132
2177- if (SAMESIGN (state -> sumX , newval ) && ! SAMESIGN ( result , state -> sumX ))
2133+ if (pg_add_s64_overflow (state -> sumX , newval , & result ))
21782134 ereport (ERROR ,
21792135 (errcode (ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE ),
21802136 errmsg ("fixeddecimal out of range" )));
@@ -2183,7 +2139,6 @@ fixeddecimal_accum(FixedDecimalAggState *state, int64 newval)
21832139 }
21842140 else
21852141 state -> sumX = newval ;
2186- #endif /* HAVE_BUILTIN_OVERFLOW */
21872142}
21882143
21892144Datum
@@ -2264,7 +2219,7 @@ Datum
22642219fixeddecimalaggstateout (PG_FUNCTION_ARGS )
22652220{
22662221 FixedDecimalAggState * state = (FixedDecimalAggState * ) PG_GETARG_POINTER (0 );
2267- char buf [MAXINT8LEN + 1 + MAXINT8LEN + 1 ];
2222+ char buf [FIXEDDECIMAL_INT64STRLEN + 1 + FIXEDDECIMAL_INT64STRLEN + 1 ];
22682223 char * p ;
22692224
22702225 p = fixeddecimal2str (state -> sumX , buf );
@@ -2318,6 +2273,9 @@ fixeddecimalaggstateserialize(PG_FUNCTION_ARGS)
23182273 if (!AggCheckCallContext (fcinfo , NULL ))
23192274 elog (ERROR , "aggregate function called in non-aggregate context" );
23202275
2276+ if (PG_ARGISNULL (0 ))
2277+ PG_RETURN_NULL ();
2278+
23212279 state = (FixedDecimalAggState * ) PG_GETARG_POINTER (0 );
23222280
23232281 pq_begintypsend (& buf );
@@ -2343,6 +2301,9 @@ fixeddecimalaggstatedeserialize(PG_FUNCTION_ARGS)
23432301 if (!AggCheckCallContext (fcinfo , NULL ))
23442302 elog (ERROR , "aggregate function called in non-aggregate context" );
23452303
2304+ if (PG_ARGISNULL (0 ))
2305+ PG_RETURN_NULL ();
2306+
23462307 sstate = PG_GETARG_BYTEA_P (0 );
23472308
23482309 /*
@@ -2395,7 +2356,10 @@ fixeddecimalaggstatecombine(PG_FUNCTION_ARGS)
23952356 PG_GETARG_POINTER (1 );
23962357
23972358 if (transstate == NULL )
2359+ {
2360+ MemoryContextSwitchTo (old_context );
23982361 PG_RETURN_POINTER (collectstate );
2362+ }
23992363
24002364 collectstate -> sumX = DatumGetInt64 (DirectFunctionCall2 (fixeddecimalpl ,
24012365 Int64GetDatum (collectstate -> sumX ), Int64GetDatum (transstate -> sumX )));
0 commit comments