aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/int8.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/int8.c')
-rw-r--r--src/backend/utils/adt/int8.c377
1 files changed, 94 insertions, 283 deletions
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index afa434cfee2..bc8dad5c5d8 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -17,6 +17,7 @@
#include <limits.h>
#include <math.h>
+#include "common/int.h"
#include "funcapi.h"
#include "libpq/pqformat.h"
#include "utils/int8.h"
@@ -25,8 +26,6 @@
#define MAXINT8LEN 25
-#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
-
typedef struct
{
int64 current;
@@ -56,11 +55,14 @@ scanint8(const char *str, bool errorOK, int64 *result)
{
const char *ptr = str;
int64 tmp = 0;
- int sign = 1;
+ bool neg = false;
/*
* Do our own scan, rather than relying on sscanf which might be broken
* for long long.
+ *
+ * As INT64_MIN can't be stored as a positive 64 bit integer, accumulate
+ * value as a negative number.
*/
/* skip leading spaces */
@@ -71,72 +73,60 @@ scanint8(const char *str, bool errorOK, int64 *result)
if (*ptr == '-')
{
ptr++;
-
- /*
- * Do an explicit check for INT64_MIN. Ugly though this is, it's
- * cleaner than trying to get the loop below to handle it portably.
- */
- if (strncmp(ptr, "9223372036854775808", 19) == 0)
- {
- tmp = PG_INT64_MIN;
- ptr += 19;
- goto gotdigits;
- }
- sign = -1;
+ neg = true;
}
else if (*ptr == '+')
ptr++;
/* require at least one digit */
- if (!isdigit((unsigned char) *ptr))
+ if (unlikely(!isdigit((unsigned char) *ptr)))
{
- if (errorOK)
- return false;
- else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for integer: \"%s\"",
- str)));
+ goto invalid_syntax;
}
/* process digits */
while (*ptr && isdigit((unsigned char) *ptr))
{
- int64 newtmp = tmp * 10 + (*ptr++ - '0');
-
- if ((newtmp / 10) != tmp) /* overflow? */
- {
- if (errorOK)
- return false;
- else
- ereport(ERROR,
- (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("value \"%s\" is out of range for type %s",
- str, "bigint")));
- }
- tmp = newtmp;
- }
+ int8 digit = (*ptr++ - '0');
-gotdigits:
+ if (unlikely(pg_mul_s64_overflow(tmp, 10, &tmp)) ||
+ unlikely(pg_sub_s64_overflow(tmp, digit, &tmp)))
+ goto out_of_range;
+ }
/* allow trailing whitespace, but not other trailing chars */
while (*ptr != '\0' && isspace((unsigned char) *ptr))
ptr++;
- if (*ptr != '\0')
+ if (unlikely(*ptr != '\0'))
+ goto invalid_syntax;
+
+ if (!neg)
{
- if (errorOK)
- return false;
- else
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for integer: \"%s\"",
- str)));
+ if (unlikely(tmp == INT64_MIN))
+ goto out_of_range;
+ tmp = -tmp;
}
-
- *result = (sign < 0) ? -tmp : tmp;
+ *result = tmp;
return true;
+
+out_of_range:
+ if (errorOK)
+ return false;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("value \"%s\" is out of range for type %s",
+ str, "bigint")));
+invalid_syntax:
+ if (errorOK)
+ return false;
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+ errmsg("invalid input syntax for integer: \"%s\"",
+ str)));
}
/* int8in()
@@ -492,12 +482,11 @@ int8um(PG_FUNCTION_ARGS)
int64 arg = PG_GETARG_INT64(0);
int64 result;
- result = -arg;
- /* overflow check (needed for INT64_MIN) */
- if (arg != 0 && SAMESIGN(result, arg))
+ if (unlikely(arg == PG_INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = -arg;
PG_RETURN_INT64(result);
}
@@ -516,14 +505,7 @@ int8pl(PG_FUNCTION_ARGS)
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -537,14 +519,7 @@ int8mi(PG_FUNCTION_ARGS)
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow(arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -558,28 +533,10 @@ int8mul(PG_FUNCTION_ARGS)
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg2 gives arg1
- * again. There are two cases where this fails: arg2 = 0 (which cannot
- * overflow) and arg1 = INT64_MIN, arg2 = -1 (where the division itself
- * will overflow and thus incorrectly match).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg1 != (int64) ((int32) arg1) || arg2 != (int64) ((int32) arg2))
- {
- if (arg2 != 0 &&
- ((arg2 == -1 && arg1 < 0 && result < 0) ||
- result / arg2 != arg1))
- ereport(ERROR,
- (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("bigint out of range")));
- }
+ if (unlikely(pg_mul_s64_overflow(arg1, arg2, &result)))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
PG_RETURN_INT64(result);
}
@@ -607,12 +564,11 @@ int8div(PG_FUNCTION_ARGS)
*/
if (arg2 == -1)
{
- result = -arg1;
- /* overflow check (needed for INT64_MIN) */
- if (arg1 != 0 && SAMESIGN(result, arg1))
+ if (unlikely(arg1 == INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = -arg1;
PG_RETURN_INT64(result);
}
@@ -632,12 +588,11 @@ int8abs(PG_FUNCTION_ARGS)
int64 arg1 = PG_GETARG_INT64(0);
int64 result;
- result = (arg1 < 0) ? -arg1 : arg1;
- /* overflow check (needed for INT64_MIN) */
- if (result < 0)
+ if (unlikely(arg1 == INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = (arg1 < 0) ? -arg1 : arg1;
PG_RETURN_INT64(result);
}
@@ -650,7 +605,7 @@ int8mod(PG_FUNCTION_ARGS)
int64 arg1 = PG_GETARG_INT64(0);
int64 arg2 = PG_GETARG_INT64(1);
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
@@ -687,16 +642,12 @@ int8inc(PG_FUNCTION_ARGS)
if (AggCheckCallContext(fcinfo, NULL))
{
int64 *arg = (int64 *) PG_GETARG_POINTER(0);
- int64 result;
- result = *arg + 1;
- /* Overflow check */
- if (result < 0 && *arg > 0)
+ if (unlikely(pg_add_s64_overflow(*arg, 1, arg)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
- *arg = result;
PG_RETURN_POINTER(arg);
}
else
@@ -706,9 +657,7 @@ int8inc(PG_FUNCTION_ARGS)
int64 arg = PG_GETARG_INT64(0);
int64 result;
- result = arg + 1;
- /* Overflow check */
- if (result < 0 && arg > 0)
+ if (unlikely(pg_add_s64_overflow(arg, 1, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -731,16 +680,11 @@ int8dec(PG_FUNCTION_ARGS)
if (AggCheckCallContext(fcinfo, NULL))
{
int64 *arg = (int64 *) PG_GETARG_POINTER(0);
- int64 result;
- result = *arg - 1;
- /* Overflow check */
- if (result > 0 && *arg < 0)
+ if (unlikely(pg_sub_s64_overflow(*arg, 1, arg)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
-
- *arg = result;
PG_RETURN_POINTER(arg);
}
else
@@ -750,9 +694,7 @@ int8dec(PG_FUNCTION_ARGS)
int64 arg = PG_GETARG_INT64(0);
int64 result;
- result = arg - 1;
- /* Overflow check */
- if (result > 0 && arg < 0)
+ if (unlikely(pg_sub_s64_overflow(arg, 1, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -821,14 +763,7 @@ int84pl(PG_FUNCTION_ARGS)
int32 arg2 = PG_GETARG_INT32(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -842,14 +777,7 @@ int84mi(PG_FUNCTION_ARGS)
int32 arg2 = PG_GETARG_INT32(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -863,20 +791,7 @@ int84mul(PG_FUNCTION_ARGS)
int32 arg2 = PG_GETARG_INT32(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg1 gives arg2
- * again. There is one case where this fails: arg1 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg1 != (int64) ((int32) arg1) &&
- result / arg1 != arg2)
+ if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -907,12 +822,11 @@ int84div(PG_FUNCTION_ARGS)
*/
if (arg2 == -1)
{
- result = -arg1;
- /* overflow check (needed for INT64_MIN) */
- if (arg1 != 0 && SAMESIGN(result, arg1))
+ if (unlikely(arg1 == INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = -arg1;
PG_RETURN_INT64(result);
}
@@ -930,14 +844,7 @@ int48pl(PG_FUNCTION_ARGS)
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -951,14 +858,7 @@ int48mi(PG_FUNCTION_ARGS)
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -972,20 +872,7 @@ int48mul(PG_FUNCTION_ARGS)
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg2 gives arg1
- * again. There is one case where this fails: arg2 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg2 != (int64) ((int32) arg2) &&
- result / arg2 != arg1)
+ if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -998,7 +885,7 @@ int48div(PG_FUNCTION_ARGS)
int32 arg1 = PG_GETARG_INT32(0);
int64 arg2 = PG_GETARG_INT64(1);
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
@@ -1018,14 +905,7 @@ int82pl(PG_FUNCTION_ARGS)
int16 arg2 = PG_GETARG_INT16(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -1039,14 +919,7 @@ int82mi(PG_FUNCTION_ARGS)
int16 arg2 = PG_GETARG_INT16(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -1060,20 +933,7 @@ int82mul(PG_FUNCTION_ARGS)
int16 arg2 = PG_GETARG_INT16(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg1 gives arg2
- * again. There is one case where this fails: arg1 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg1 != (int64) ((int32) arg1) &&
- result / arg1 != arg2)
+ if (unlikely(pg_mul_s64_overflow(arg1, (int64) arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -1087,7 +947,7 @@ int82div(PG_FUNCTION_ARGS)
int16 arg2 = PG_GETARG_INT16(1);
int64 result;
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
@@ -1104,12 +964,11 @@ int82div(PG_FUNCTION_ARGS)
*/
if (arg2 == -1)
{
- result = -arg1;
- /* overflow check (needed for INT64_MIN) */
- if (arg1 != 0 && SAMESIGN(result, arg1))
+ if (unlikely(arg1 == INT64_MIN))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = -arg1;
PG_RETURN_INT64(result);
}
@@ -1127,14 +986,7 @@ int28pl(PG_FUNCTION_ARGS)
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 + arg2;
-
- /*
- * Overflow check. If the inputs are of different signs then their sum
- * cannot overflow. If the inputs are of the same sign, their sum had
- * better be that sign too.
- */
- if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_add_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -1148,14 +1000,7 @@ int28mi(PG_FUNCTION_ARGS)
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 - arg2;
-
- /*
- * Overflow check. If the inputs are of the same sign then their
- * difference cannot overflow. If they are of different signs then the
- * result should be of the same sign as the first input.
- */
- if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
+ if (unlikely(pg_sub_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -1169,20 +1014,7 @@ int28mul(PG_FUNCTION_ARGS)
int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = arg1 * arg2;
-
- /*
- * Overflow check. We basically check to see if result / arg2 gives arg1
- * again. There is one case where this fails: arg2 = 0 (which cannot
- * overflow).
- *
- * Since the division is likely much more expensive than the actual
- * multiplication, we'd like to skip it where possible. The best bang for
- * the buck seems to be to check whether both inputs are in the int32
- * range; if so, no overflow is possible.
- */
- if (arg2 != (int64) ((int32) arg2) &&
- result / arg2 != arg1)
+ if (unlikely(pg_mul_s64_overflow((int64) arg1, arg2, &result)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
@@ -1195,7 +1027,7 @@ int28div(PG_FUNCTION_ARGS)
int16 arg1 = PG_GETARG_INT16(0);
int64 arg2 = PG_GETARG_INT64(1);
- if (arg2 == 0)
+ if (unlikely(arg2 == 0))
{
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
@@ -1287,17 +1119,13 @@ Datum
int84(PG_FUNCTION_ARGS)
{
int64 arg = PG_GETARG_INT64(0);
- int32 result;
-
- result = (int32) arg;
- /* Test for overflow by reverse-conversion. */
- if ((int64) result != arg)
+ if (unlikely(arg < PG_INT32_MIN) || unlikely(arg > PG_INT32_MAX))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
- PG_RETURN_INT32(result);
+ PG_RETURN_INT32((int32) arg);
}
Datum
@@ -1312,17 +1140,13 @@ Datum
int82(PG_FUNCTION_ARGS)
{
int64 arg = PG_GETARG_INT64(0);
- int16 result;
- result = (int16) arg;
-
- /* Test for overflow by reverse-conversion. */
- if ((int64) result != arg)
+ if (unlikely(arg < PG_INT16_MIN) || unlikely(arg > PG_INT16_MAX))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("smallint out of range")));
- PG_RETURN_INT16(result);
+ PG_RETURN_INT16((int16) arg);
}
Datum
@@ -1348,18 +1172,15 @@ dtoi8(PG_FUNCTION_ARGS)
/* Round arg to nearest integer (but it's still in float form) */
arg = rint(arg);
- /*
- * Does it fit in an int64? Avoid assuming that we have handy constants
- * defined for the range boundaries, instead test for overflow by
- * reverse-conversion.
- */
- result = (int64) arg;
-
- if ((float8) result != arg)
+ if (unlikely(arg < (double) PG_INT64_MIN) ||
+ unlikely(arg > (double) PG_INT64_MAX) ||
+ unlikely(isnan(arg)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
+ result = (int64) arg;
+
PG_RETURN_INT64(result);
}
@@ -1381,42 +1202,32 @@ Datum
ftoi8(PG_FUNCTION_ARGS)
{
float4 arg = PG_GETARG_FLOAT4(0);
- int64 result;
float8 darg;
/* Round arg to nearest integer (but it's still in float form) */
darg = rint(arg);
- /*
- * Does it fit in an int64? Avoid assuming that we have handy constants
- * defined for the range boundaries, instead test for overflow by
- * reverse-conversion.
- */
- result = (int64) darg;
-
- if ((float8) result != darg)
+ if (unlikely(arg < (float4) PG_INT64_MIN) ||
+ unlikely(arg > (float4) PG_INT64_MAX) ||
+ unlikely(isnan(arg)))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("bigint out of range")));
- PG_RETURN_INT64(result);
+ PG_RETURN_INT64((int64) darg);
}
Datum
i8tooid(PG_FUNCTION_ARGS)
{
int64 arg = PG_GETARG_INT64(0);
- Oid result;
-
- result = (Oid) arg;
- /* Test for overflow by reverse-conversion. */
- if ((int64) result != arg)
+ if (unlikely(arg < 0) || unlikely(arg > PG_UINT32_MAX))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("OID out of range")));
- PG_RETURN_OID(result);
+ PG_RETURN_OID((Oid) arg);
}
Datum
@@ -1494,11 +1305,11 @@ generate_series_step_int8(PG_FUNCTION_ARGS)
if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
(fctx->step < 0 && fctx->current >= fctx->finish))
{
- /* increment current in preparation for next iteration */
- fctx->current += fctx->step;
-
- /* if next-value computation overflows, this is the final result */
- if (SAMESIGN(result, fctx->step) && !SAMESIGN(result, fctx->current))
+ /*
+ * Increment current in preparation for next iteration. If next-value
+ * computation overflows, this is the final result.
+ */
+ if (pg_add_s64_overflow(fctx->current, fctx->step, &fctx->current))
fctx->step = 0;
/* do when there is more left to send */