From f3d02385d7914e540c6eaf0ee506d0161d265380 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 31 Aug 2017 13:25:28 -0700
Subject: [PATCH 06/16] WIP: deduplicate int/float overflow handling code.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/utils/adt/float.c |  26 +++++++---
 src/backend/utils/adt/int8.c  | 113 +++++++++++++-----------------------------
 2 files changed, 54 insertions(+), 85 deletions(-)

diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 18b3b949ac..78c06b6c41 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -47,20 +47,31 @@ static const uint32 nan[2] = {0xffffffff, 0x7fffffff};
 #define MAXFLOATWIDTH	64
 #define MAXDOUBLEWIDTH	128
 
+static void
+floaterr(bool is_overflow)
+{
+	if (is_overflow)
+		ereport(ERROR,											\
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),	\
+		  errmsg("value out of range: overflow")));				\
+	else
+		ereport(ERROR,											\
+				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),	\
+		 errmsg("value out of range: underflow")));				\
+}
+
+#undef isinf
+#define isinf __builtin_isinf
+
 /*
  * check to see if a float4/8 val has underflowed or overflowed
  */
 #define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid)			\
 do {															\
 	if (isinf(val) && !(inf_is_valid))							\
-		ereport(ERROR,											\
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),	\
-		  errmsg("value out of range: overflow")));				\
-																\
+		floaterr(true);											\
 	if ((val) == 0.0 && !(zero_is_valid))						\
-		ereport(ERROR,											\
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),	\
-		 errmsg("value out of range: underflow")));				\
+		floaterr(false);										\
 } while(0)
 
 
@@ -903,6 +914,7 @@ float8mul(PG_FUNCTION_ARGS)
 
 	CHECKFLOATVAL(result, isinf(arg1) || isinf(arg2),
 				  arg1 == 0 || arg2 == 0);
+
 	PG_RETURN_FLOAT8(result);
 }
 
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index e8354dee44..8b95a7c479 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -45,6 +45,14 @@ typedef struct
  * Formatting and conversion routines.
  *---------------------------------------------------------*/
 
+static void
+overflowerr(void)
+{
+	ereport(ERROR,
+			(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+			 errmsg("bigint out of range")));
+}
+
 /*
  * scanint8 --- try to parse a string into an int8.
  *
@@ -495,9 +503,7 @@ int8um(PG_FUNCTION_ARGS)
 	result = -arg;
 	/* overflow check (needed for INT64_MIN) */
 	if (arg != 0 && SAMESIGN(result, arg))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -524,9 +530,7 @@ int8pl(PG_FUNCTION_ARGS)
 	 * better be that sign too.
 	 */
 	if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -545,9 +549,8 @@ int8mi(PG_FUNCTION_ARGS)
 	 * result should be of the same sign as the first input.
 	 */
 	if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
+
 	PG_RETURN_INT64(result);
 }
 
@@ -576,9 +579,7 @@ int8mul(PG_FUNCTION_ARGS)
 		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")));
+			overflowerr();
 	}
 	PG_RETURN_INT64(result);
 }
@@ -610,9 +611,7 @@ int8div(PG_FUNCTION_ARGS)
 		result = -arg1;
 		/* overflow check (needed for INT64_MIN) */
 		if (arg1 != 0 && SAMESIGN(result, arg1))
-			ereport(ERROR,
-					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-					 errmsg("bigint out of range")));
+			overflowerr();
 		PG_RETURN_INT64(result);
 	}
 
@@ -635,9 +634,7 @@ int8abs(PG_FUNCTION_ARGS)
 	result = (arg1 < 0) ? -arg1 : arg1;
 	/* overflow check (needed for INT64_MIN) */
 	if (result < 0)
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -692,9 +689,7 @@ int8inc(PG_FUNCTION_ARGS)
 		result = *arg + 1;
 		/* Overflow check */
 		if (result < 0 && *arg > 0)
-			ereport(ERROR,
-					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-					 errmsg("bigint out of range")));
+			overflowerr();
 
 		*arg = result;
 		PG_RETURN_POINTER(arg);
@@ -709,9 +704,7 @@ int8inc(PG_FUNCTION_ARGS)
 		result = arg + 1;
 		/* Overflow check */
 		if (result < 0 && arg > 0)
-			ereport(ERROR,
-					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-					 errmsg("bigint out of range")));
+			overflowerr();
 
 		PG_RETURN_INT64(result);
 	}
@@ -736,9 +729,7 @@ int8dec(PG_FUNCTION_ARGS)
 		result = *arg - 1;
 		/* Overflow check */
 		if (result > 0 && *arg < 0)
-			ereport(ERROR,
-					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-					 errmsg("bigint out of range")));
+			overflowerr();
 
 		*arg = result;
 		PG_RETURN_POINTER(arg);
@@ -753,9 +744,7 @@ int8dec(PG_FUNCTION_ARGS)
 		result = arg - 1;
 		/* Overflow check */
 		if (result > 0 && arg < 0)
-			ereport(ERROR,
-					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-					 errmsg("bigint out of range")));
+			overflowerr();
 
 		PG_RETURN_INT64(result);
 	}
@@ -829,9 +818,7 @@ int84pl(PG_FUNCTION_ARGS)
 	 * better be that sign too.
 	 */
 	if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -850,9 +837,7 @@ int84mi(PG_FUNCTION_ARGS)
 	 * result should be of the same sign as the first input.
 	 */
 	if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -877,9 +862,7 @@ int84mul(PG_FUNCTION_ARGS)
 	 */
 	if (arg1 != (int64) ((int32) arg1) &&
 		result / arg1 != arg2)
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -910,9 +893,7 @@ int84div(PG_FUNCTION_ARGS)
 		result = -arg1;
 		/* overflow check (needed for INT64_MIN) */
 		if (arg1 != 0 && SAMESIGN(result, arg1))
-			ereport(ERROR,
-					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-					 errmsg("bigint out of range")));
+			overflowerr();
 		PG_RETURN_INT64(result);
 	}
 
@@ -938,9 +919,7 @@ int48pl(PG_FUNCTION_ARGS)
 	 * better be that sign too.
 	 */
 	if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -959,9 +938,7 @@ int48mi(PG_FUNCTION_ARGS)
 	 * result should be of the same sign as the first input.
 	 */
 	if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -986,9 +963,7 @@ int48mul(PG_FUNCTION_ARGS)
 	 */
 	if (arg2 != (int64) ((int32) arg2) &&
 		result / arg2 != arg1)
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -1026,9 +1001,7 @@ int82pl(PG_FUNCTION_ARGS)
 	 * better be that sign too.
 	 */
 	if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -1047,9 +1020,7 @@ int82mi(PG_FUNCTION_ARGS)
 	 * result should be of the same sign as the first input.
 	 */
 	if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -1074,9 +1045,7 @@ int82mul(PG_FUNCTION_ARGS)
 	 */
 	if (arg1 != (int64) ((int32) arg1) &&
 		result / arg1 != arg2)
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -1107,9 +1076,7 @@ int82div(PG_FUNCTION_ARGS)
 		result = -arg1;
 		/* overflow check (needed for INT64_MIN) */
 		if (arg1 != 0 && SAMESIGN(result, arg1))
-			ereport(ERROR,
-					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-					 errmsg("bigint out of range")));
+			overflowerr();
 		PG_RETURN_INT64(result);
 	}
 
@@ -1135,9 +1102,7 @@ int28pl(PG_FUNCTION_ARGS)
 	 * better be that sign too.
 	 */
 	if (SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -1156,9 +1121,7 @@ int28mi(PG_FUNCTION_ARGS)
 	 * result should be of the same sign as the first input.
 	 */
 	if (!SAMESIGN(arg1, arg2) && !SAMESIGN(result, arg1))
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -1183,9 +1146,7 @@ int28mul(PG_FUNCTION_ARGS)
 	 */
 	if (arg2 != (int64) ((int32) arg2) &&
 		result / arg2 != arg1)
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 	PG_RETURN_INT64(result);
 }
 
@@ -1356,9 +1317,7 @@ dtoi8(PG_FUNCTION_ARGS)
 	result = (int64) arg;
 
 	if ((float8) result != arg)
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 
 	PG_RETURN_INT64(result);
 }
@@ -1395,9 +1354,7 @@ ftoi8(PG_FUNCTION_ARGS)
 	result = (int64) darg;
 
 	if ((float8) result != darg)
-		ereport(ERROR,
-				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
-				 errmsg("bigint out of range")));
+		overflowerr();
 
 	PG_RETURN_INT64(result);
 }
-- 
2.14.1.2.g4274c698f4.dirty

