v3-keep-compiler-silence.patch
application/octet-stream
Filename: v3-keep-compiler-silence.patch
Type: application/octet-stream
Part: 1
Patch
Format: unified
Series: patch v3
| File | + | − |
|---|---|---|
| src/backend/utils/adt/timestamp.c | 1 | 1 |
| src/bin/pgbench/pgbench.c | 1 | 1 |
| src/include/c.h | 19 | 0 |
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 84bc97d40c..b3bfb21879 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -3233,7 +3233,7 @@ interval_mul(PG_FUNCTION_ARGS)
/* cascade units down */
result->day += (int32) month_remainder_days;
result_double = rint(span->time * factor + sec_remainder * USECS_PER_SEC);
- if (result_double > PG_INT64_MAX || result_double < PG_INT64_MIN)
+ if (!IS_DOUBLE_SAFE_IN_INT64(result_double))
ereport(ERROR,
(errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
errmsg("interval out of range")));
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index ed7652bfbf..6deed64ca4 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -1654,7 +1654,7 @@ coerceToInt(PgBenchValue *pval, int64 *ival)
{
double dval = pval->u.dval;
- if (dval < PG_INT64_MIN || PG_INT64_MAX < dval)
+ if (!IS_DOUBLE_SAFE_IN_INT64(dval))
{
fprintf(stderr, "double to int overflow for %f\n", dval);
return false;
diff --git a/src/include/c.h b/src/include/c.h
index f461628a24..b70e947ae6 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -444,6 +444,25 @@ typedef unsigned PG_INT128_TYPE uint128
#define PG_INT64_MAX INT64CONST(0x7FFFFFFFFFFFFFFF)
#define PG_UINT64_MAX UINT64CONST(0xFFFFFFFFFFFFFFFF)
+/*
+ * Check if a double value can be casted into int64.
+ *
+ * This macro is assuming that FLT_RADIX == 2 so that the * 2.0 trick works,
+ * PG_INT64_MAX is so below DBL_MAX that the doubled value can be represented
+ * in double and DBL_MANT_DIG is equal or smaller than DBL_MAX_EXP so that
+ * ceil() returns expected result.
+ */
+#define MIN_DOUBLE_OVER_INT64_MAX (2.0 * (double) (PG_INT64_MAX / 2 + 1))
+#define MAX_DOUBLE_UNDER_INT64_MIN (2.0 * (double) (PG_INT64_MIN / 2 - 1))
+
+#if -PG_INT64_MAX != PG_INT64_MIN
+#define IS_DOUBLE_SAFE_IN_INT64(x) \
+ ((x) < MIN_DOUBLE_OVER_INT64_MAX && ceil(x) >= (double) PG_INT64_MIN)
+#else
+#define IS_DOUBLE_SAFE_IN_INT64(x) \
+ ((x) < MIN_DOUBLE_OVER_INT64_MAX && (x) > MAX_DOUBLE_UNDER_INT64_MIN)
+#endif
+
/* Max value of size_t might also be missing if we don't have stdint.h */
#ifndef SIZE_MAX
#if SIZEOF_SIZE_T == 8