summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane2004-10-04 14:42:48 +0000
committerTom Lane2004-10-04 14:42:48 +0000
commit4171bb869f234281a13bb862d3b1e577bf336242 (patch)
treee8193f7be04ddd942f13811ef9bbe0494d24920d
parent24201b4bc60e46e8de031fb5911af32bdb412d43 (diff)
Detect overflow in integer arithmetic operators (integer, smallint, and
bigint variants). Clean up some inconsistencies in error message wording. Fix scanint8 to allow trailing whitespace in INT64_MIN case. Update int8-exp-three-digits.out, which seems to have been ignored by the last couple of people to modify the int8 regression test, and remove int8-exp-three-digits-win32.out which is thereby exposed as redundant.
-rw-r--r--doc/src/sgml/release.sgml15
-rw-r--r--src/backend/utils/adt/float.c6
-rw-r--r--src/backend/utils/adt/int.c283
-rw-r--r--src/backend/utils/adt/int8.c380
-rw-r--r--src/backend/utils/adt/numeric.c12
-rw-r--r--src/backend/utils/adt/numutils.c4
-rw-r--r--src/backend/utils/adt/varbit.c4
-rw-r--r--src/test/regress/expected/int2.out43
-rw-r--r--src/test/regress/expected/int4.out82
-rw-r--r--src/test/regress/expected/int8-exp-three-digits-win32.out300
-rw-r--r--src/test/regress/expected/int8-exp-three-digits.out45
-rw-r--r--src/test/regress/expected/int8.out16
-rw-r--r--src/test/regress/expected/subselect.out3
-rw-r--r--src/test/regress/resultmap2
-rw-r--r--src/test/regress/sql/int2.sql9
-rw-r--r--src/test/regress/sql/int4.sql18
-rw-r--r--src/test/regress/sql/int8.sql1
-rw-r--r--src/test/regress/sql/subselect.sql3
18 files changed, 702 insertions, 524 deletions
diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
index f6601ce1cc..20ea24d3f0 100644
--- a/doc/src/sgml/release.sgml
+++ b/doc/src/sgml/release.sgml
@@ -1,5 +1,5 @@
<!--
-$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.298 2004/10/01 02:00:43 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.299 2004/10/04 14:42:46 tgl Exp $
-->
<appendix id="release">
@@ -258,6 +258,13 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.298 2004/10/01 02:00:43 neilc E
<listitem>
<para>
+ Overflow in integer arithmetic operations is now detected and
+ reported as an error.
+ </para>
+ </listitem>
+
+ <listitem>
+ <para>
The server now warns of empty strings passed to
<type>oid</type>/<type>float4</type>/<type>float8</type> data
types. In the next major release, doing this will generate an
@@ -1228,6 +1235,12 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.298 2004/10/01 02:00:43 neilc E
</para>
</listitem>
+ <listitem>
+ <para>
+ Overflow in integer arithmetic operations is now detected (Tom)
+ </para>
+ </listitem>
+
<listitem>
<para>
Syntax checking of array input values considerably tightened up (Joe)
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index ccee67319c..9bb521183a 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.110 2004/09/02 17:12:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.111 2004/10/04 14:42:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1147,7 +1147,7 @@ dtoi2(PG_FUNCTION_ARGS)
if ((num < SHRT_MIN) || (num > SHRT_MAX))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("smallint out of range")));
result = (int16) rint(num);
PG_RETURN_INT16(result);
@@ -1213,7 +1213,7 @@ ftoi2(PG_FUNCTION_ARGS)
if ((num < SHRT_MIN) || (num > SHRT_MAX))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("smallint out of range")));
result = (int16) rint(num);
PG_RETURN_INT16(result);
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 1183fa9aa0..7dde75014e 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.62 2004/08/29 05:06:49 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/int.c,v 1.63 2004/10/04 14:42:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,7 +28,6 @@
* Arithmetic operators:
* intmod
*/
-
#include "postgres.h"
#include <ctype.h>
@@ -38,6 +37,7 @@
#include "libpq/pqformat.h"
#include "utils/builtins.h"
+
#ifndef SHRT_MAX
#define SHRT_MAX (0x7FFF)
#endif
@@ -45,6 +45,8 @@
#define SHRT_MIN (-0x8000)
#endif
+#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
+
typedef struct
{
int32 current;
@@ -52,6 +54,7 @@ typedef struct
int32 step;
} generate_series_fctx;
+
/*****************************************************************************
* USER I/O ROUTINES *
*****************************************************************************/
@@ -291,7 +294,7 @@ i4toi2(PG_FUNCTION_ARGS)
if (arg1 < SHRT_MIN || arg1 > SHRT_MAX)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("smallint out of range")));
PG_RETURN_INT16((int16) arg1);
}
@@ -601,8 +604,15 @@ Datum
int4um(PG_FUNCTION_ARGS)
{
int32 arg = PG_GETARG_INT32(0);
+ int32 result;
- PG_RETURN_INT32(-arg);
+ result = -arg;
+ /* overflow check (needed for INT_MIN) */
+ if (arg != 0 && SAMESIGN(result, arg))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -618,8 +628,19 @@ int4pl(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1);
+ int32 result;
- PG_RETURN_INT32(arg1 + arg2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -627,8 +648,19 @@ int4mi(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1);
+ int32 result;
- PG_RETURN_INT32(arg1 - arg2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -636,8 +668,28 @@ int4mul(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1);
+ int32 result;
- PG_RETURN_INT32(arg1 * arg2);
+ 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 = INT_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 int16 range; if so, no overflow is possible.
+ */
+ if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX &&
+ arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
+ arg2 != 0 &&
+ (result/arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -645,29 +697,55 @@ int4div(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1);
+ int32 result;
if (arg2 == 0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
- PG_RETURN_INT32(arg1 / arg2);
+ result = arg1 / arg2;
+ /*
+ * Overflow check. The only possible overflow case is for
+ * arg1 = INT_MIN, arg2 = -1, where the correct result is -INT_MIN,
+ * which can't be represented on a two's-complement machine.
+ */
+ if (arg2 == -1 && arg1 < 0 && result < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
int4inc(PG_FUNCTION_ARGS)
{
int32 arg = PG_GETARG_INT32(0);
+ int32 result;
- PG_RETURN_INT32(arg + 1);
+ result = arg + 1;
+ /* Overflow check */
+ if (arg > 0 && result < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+
+ PG_RETURN_INT32(result);
}
Datum
int2um(PG_FUNCTION_ARGS)
{
int16 arg = PG_GETARG_INT16(0);
+ int16 result;
- PG_RETURN_INT16(-arg);
+ result = -arg;
+ /* overflow check (needed for SHRT_MIN) */
+ if (arg != 0 && SAMESIGN(result, arg))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("smallint out of range")));
+ PG_RETURN_INT16(result);
}
Datum
@@ -683,8 +761,19 @@ int2pl(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1);
+ int16 result;
- PG_RETURN_INT16(arg1 + arg2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("smallint out of range")));
+ PG_RETURN_INT16(result);
}
Datum
@@ -692,8 +781,19 @@ int2mi(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1);
+ int16 result;
- PG_RETURN_INT16(arg1 - arg2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("smallint out of range")));
+ PG_RETURN_INT16(result);
}
Datum
@@ -701,8 +801,20 @@ int2mul(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1);
+ int32 result32;
- PG_RETURN_INT16(arg1 * arg2);
+ /*
+ * The most practical way to detect overflow is to do the arithmetic
+ * in int32 (so that the result can't overflow) and then do a range
+ * check.
+ */
+ result32 = (int32) arg1 * (int32) arg2;
+ if (result32 < SHRT_MIN || result32 > SHRT_MAX)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("smallint out of range")));
+
+ PG_RETURN_INT16((int16) result32);
}
Datum
@@ -710,13 +822,24 @@ int2div(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1);
+ int16 result;
if (arg2 == 0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
- PG_RETURN_INT16(arg1 / arg2);
+ result = arg1 / arg2;
+ /*
+ * Overflow check. The only possible overflow case is for
+ * arg1 = SHRT_MIN, arg2 = -1, where the correct result is -SHRT_MIN,
+ * which can't be represented on a two's-complement machine.
+ */
+ if (arg2 == -1 && arg1 < 0 && result < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("smallint out of range")));
+ PG_RETURN_INT16(result);
}
Datum
@@ -724,8 +847,19 @@ int24pl(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
int32 arg2 = PG_GETARG_INT32(1);
+ int32 result;
- PG_RETURN_INT32(arg1 + arg2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -733,8 +867,19 @@ int24mi(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
int32 arg2 = PG_GETARG_INT32(1);
+ int32 result;
- PG_RETURN_INT32(arg1 - arg2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -742,8 +887,25 @@ int24mul(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
int32 arg2 = PG_GETARG_INT32(1);
+ int32 result;
- PG_RETURN_INT32(arg1 * arg2);
+ 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 int16 range; if so, no overflow is possible.
+ */
+ if (!(arg2 >= (int32) SHRT_MIN && arg2 <= (int32) SHRT_MAX) &&
+ result/arg2 != arg1)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -756,8 +918,8 @@ int24div(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
-
- PG_RETURN_INT32(arg1 / arg2);
+ /* No overflow is possible */
+ PG_RETURN_INT32((int32) arg1 / arg2);
}
Datum
@@ -765,8 +927,19 @@ int42pl(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int16 arg2 = PG_GETARG_INT16(1);
+ int32 result;
- PG_RETURN_INT32(arg1 + arg2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -774,8 +947,19 @@ int42mi(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int16 arg2 = PG_GETARG_INT16(1);
+ int32 result;
- PG_RETURN_INT32(arg1 - arg2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -783,8 +967,25 @@ int42mul(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int16 arg2 = PG_GETARG_INT16(1);
+ int32 result;
- PG_RETURN_INT32(arg1 * arg2);
+ 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 int16 range; if so, no overflow is possible.
+ */
+ if (!(arg1 >= (int32) SHRT_MIN && arg1 <= (int32) SHRT_MAX) &&
+ result/arg1 != arg2)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -792,13 +993,24 @@ int42div(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
int16 arg2 = PG_GETARG_INT16(1);
+ int32 result;
if (arg2 == 0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
- PG_RETURN_INT32(arg1 / arg2);
+ result = arg1 / arg2;
+ /*
+ * Overflow check. The only possible overflow case is for
+ * arg1 = INT_MIN, arg2 = -1, where the correct result is -INT_MIN,
+ * which can't be represented on a two's-complement machine.
+ */
+ if (arg2 == -1 && arg1 < 0 && result < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
@@ -811,6 +1023,7 @@ int4mod(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
+ /* No overflow is possible */
PG_RETURN_INT32(arg1 % arg2);
}
@@ -825,6 +1038,7 @@ int2mod(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
+ /* No overflow is possible */
PG_RETURN_INT16(arg1 % arg2);
}
@@ -839,6 +1053,7 @@ int24mod(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
+ /* No overflow is possible */
PG_RETURN_INT32(arg1 % arg2);
}
@@ -853,6 +1068,7 @@ int42mod(PG_FUNCTION_ARGS)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
+ /* No overflow is possible */
PG_RETURN_INT32(arg1 % arg2);
}
@@ -865,16 +1081,30 @@ Datum
int4abs(PG_FUNCTION_ARGS)
{
int32 arg1 = PG_GETARG_INT32(0);
+ int32 result;
- PG_RETURN_INT32((arg1 < 0) ? -arg1 : arg1);
+ result = (arg1 < 0) ? -arg1 : arg1;
+ /* overflow check (needed for INT_MIN) */
+ if (result < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("integer out of range")));
+ PG_RETURN_INT32(result);
}
Datum
int2abs(PG_FUNCTION_ARGS)
{
int16 arg1 = PG_GETARG_INT16(0);
+ int16 result;
- PG_RETURN_INT16((arg1 < 0) ? -arg1 : arg1);
+ result = (arg1 < 0) ? -arg1 : arg1;
+ /* overflow check (needed for SHRT_MIN) */
+ if (result < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("smallint out of range")));
+ PG_RETURN_INT16(result);
}
Datum
@@ -913,7 +1143,8 @@ int4smaller(PG_FUNCTION_ARGS)
PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
}
-/* Binary arithmetics
+/*
+ * Bit-pushing operators
*
* int[24]and - returns arg1 & arg2
* int[24]or - returns arg1 | arg2
diff --git a/src/backend/utils/adt/int8.c b/src/backend/utils/adt/int8.c
index e58c94268a..96964c82b9 100644
--- a/src/backend/utils/adt/int8.c
+++ b/src/backend/utils/adt/int8.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.55 2004/08/29 05:06:49 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/int8.c,v 1.56 2004/10/04 14:42:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,8 @@
#define MAXINT8LEN 25
+#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
+
typedef struct
{
int64 current;
@@ -31,6 +33,7 @@ typedef struct
int64 step;
} generate_series_fctx;
+
/***********************************************************************
**
** Routines for 64-bit integers.
@@ -67,7 +70,6 @@ scanint8(const char *str, bool errorOK, int64 *result)
if (*ptr == '-')
{
ptr++;
- sign = -1;
/*
* Do an explicit check for INT64_MIN. Ugly though this is, it's
@@ -75,12 +77,15 @@ scanint8(const char *str, bool errorOK, int64 *result)
* portably.
*/
#ifndef INT64_IS_BUSTED
- if (strcmp(ptr, "9223372036854775808") == 0)
+ if (strncmp(ptr, "9223372036854775808", 19) == 0)
{
- *result = -INT64CONST(0x7fffffffffffffff) - 1;
- return true;
+ tmp = -INT64CONST(0x7fffffffffffffff) - 1;
+ ptr += 19;
+ goto gotdigits;
}
#endif
+
+ sign = -1;
}
else if (*ptr == '+')
ptr++;
@@ -93,7 +98,8 @@ scanint8(const char *str, bool errorOK, int64 *result)
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type bigint: \"%s\"", str)));
+ errmsg("invalid input syntax for integer: \"%s\"",
+ str)));
}
/* process digits */
@@ -108,11 +114,14 @@ scanint8(const char *str, bool errorOK, int64 *result)
else
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("value \"%s\" is out of range for type bigint",
+ str)));
}
tmp = newtmp;
}
+gotdigits:
+
/* allow trailing whitespace, but not other trailing chars */
while (*ptr != '\0' && isspace((unsigned char) *ptr))
ptr++;
@@ -124,7 +133,8 @@ scanint8(const char *str, bool errorOK, int64 *result)
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
- errmsg("invalid input syntax for type bigint: \"%s\"", str)));
+ errmsg("invalid input syntax for integer: \"%s\"",
+ str)));
}
*result = (sign < 0) ? -tmp : tmp;
@@ -485,58 +495,118 @@ int28ge(PG_FUNCTION_ARGS)
Datum
int8um(PG_FUNCTION_ARGS)
{
- int64 val = PG_GETARG_INT64(0);
+ int64 arg = PG_GETARG_INT64(0);
+ int64 result;
- PG_RETURN_INT64(-val);
+ 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")));
+ PG_RETURN_INT64(result);
}
Datum
int8up(PG_FUNCTION_ARGS)
{
- int64 val = PG_GETARG_INT64(0);
+ int64 arg = PG_GETARG_INT64(0);
- PG_RETURN_INT64(val);
+ PG_RETURN_INT64(arg);
}
Datum
int8pl(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int64 arg2 = PG_GETARG_INT64(1);
+ int64 result;
- PG_RETURN_INT64(val1 + val2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int8mi(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int64 arg2 = PG_GETARG_INT64(1);
+ int64 result;
- PG_RETURN_INT64(val1 - val2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int8mul(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int64 arg2 = PG_GETARG_INT64(1);
+ int64 result;
- PG_RETURN_INT64(val1 * val2);
+ 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)) &&
+ arg2 != 0 &&
+ (result/arg2 != arg1 || (arg2 == -1 && arg1 < 0 && result < 0)))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int8div(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int64 arg2 = PG_GETARG_INT64(1);
+ int64 result;
- if (val2 == 0)
+ if (arg2 == 0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
- PG_RETURN_INT64(val1 / val2);
+ result = arg1 / arg2;
+ /*
+ * Overflow check. The only possible overflow case is for
+ * arg1 = INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN,
+ * which can't be represented on a two's-complement machine.
+ */
+ if (arg2 == -1 && arg1 < 0 && result < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
/* int8abs()
@@ -546,8 +616,15 @@ Datum
int8abs(PG_FUNCTION_ARGS)
{
int64 arg1 = PG_GETARG_INT64(0);
+ int64 result;
- PG_RETURN_INT64((arg1 < 0) ? -arg1 : arg1);
+ 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")));
+ PG_RETURN_INT64(result);
}
/* int8mod()
@@ -556,20 +633,16 @@ int8abs(PG_FUNCTION_ARGS)
Datum
int8mod(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int64 val2 = PG_GETARG_INT64(1);
- int64 result;
+ int64 arg1 = PG_GETARG_INT64(0);
+ int64 arg2 = PG_GETARG_INT64(1);
- if (val2 == 0)
+ if (arg2 == 0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
+ /* No overflow is possible */
- result = val1 / val2;
- result *= val2;
- result = val1 - result;
-
- PG_RETURN_INT64(result);
+ PG_RETURN_INT64(arg1 % arg2);
}
@@ -577,18 +650,26 @@ Datum
int8inc(PG_FUNCTION_ARGS)
{
int64 arg = PG_GETARG_INT64(0);
+ int64 result;
- PG_RETURN_INT64(arg + 1);
+ result = arg + 1;
+ /* Overflow check */
+ if (arg > 0 && result < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+
+ PG_RETURN_INT64(result);
}
Datum
int8larger(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = ((val1 > val2) ? val1 : val2);
+ result = ((arg1 > arg2) ? arg1 : arg2);
PG_RETURN_INT64(result);
}
@@ -596,11 +677,11 @@ int8larger(PG_FUNCTION_ARGS)
Datum
int8smaller(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int64 arg2 = PG_GETARG_INT64(1);
int64 result;
- result = ((val1 < val2) ? val1 : val2);
+ result = ((arg1 < arg2) ? arg1 : arg2);
PG_RETURN_INT64(result);
}
@@ -608,83 +689,172 @@ int8smaller(PG_FUNCTION_ARGS)
Datum
int84pl(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int32 val2 = PG_GETARG_INT32(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int32 arg2 = PG_GETARG_INT32(1);
+ int64 result;
- PG_RETURN_INT64(val1 + val2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int84mi(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int32 val2 = PG_GETARG_INT32(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int32 arg2 = PG_GETARG_INT32(1);
+ int64 result;
- PG_RETURN_INT64(val1 - val2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int84mul(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int32 val2 = PG_GETARG_INT32(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int32 arg2 = PG_GETARG_INT32(1);
+ int64 result;
- PG_RETURN_INT64(val1 * val2);
+ 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)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int84div(PG_FUNCTION_ARGS)
{
- int64 val1 = PG_GETARG_INT64(0);
- int32 val2 = PG_GETARG_INT32(1);
+ int64 arg1 = PG_GETARG_INT64(0);
+ int32 arg2 = PG_GETARG_INT32(1);
+ int64 result;
- if (val2 == 0)
+ if (arg2 == 0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
- PG_RETURN_INT64(val1 / val2);
+ result = arg1 / arg2;
+ /*
+ * Overflow check. The only possible overflow case is for
+ * arg1 = INT64_MIN, arg2 = -1, where the correct result is -INT64_MIN,
+ * which can't be represented on a two's-complement machine.
+ */
+ if (arg2 == -1 && arg1 < 0 && result < 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int48pl(PG_FUNCTION_ARGS)
{
- int32 val1 = PG_GETARG_INT32(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int32 arg1 = PG_GETARG_INT32(0);
+ int64 arg2 = PG_GETARG_INT64(1);
+ int64 result;
- PG_RETURN_INT64(val1 + val2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int48mi(PG_FUNCTION_ARGS)
{
- int32 val1 = PG_GETARG_INT32(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int32 arg1 = PG_GETARG_INT32(0);
+ int64 arg2 = PG_GETARG_INT64(1);
+ int64 result;
- PG_RETURN_INT64(val1 - val2);
+ 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))
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int48mul(PG_FUNCTION_ARGS)
{
- int32 val1 = PG_GETARG_INT32(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int32 arg1 = PG_GETARG_INT32(0);
+ int64 arg2 = PG_GETARG_INT64(1);
+ int64 result;
- PG_RETURN_INT64(val1 * val2);
+ 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)
+ ereport(ERROR,
+ (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
+ errmsg("bigint out of range")));
+ PG_RETURN_INT64(result);
}
Datum
int48div(PG_FUNCTION_ARGS)
{
- int32 val1 = PG_GETARG_INT32(0);
- int64 val2 = PG_GETARG_INT64(1);
+ int32 arg1 = PG_GETARG_INT32(0);
+ int64 arg2 = PG_GETARG_INT64(1);
- if (val2 == 0)
+ if (arg2 == 0)
ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero")));
-
- PG_RETURN_INT64(val1 / val2);
+ /* No overflow is possible */
+ PG_RETURN_INT64((int64) arg1 / arg2);
}
/* Binary arithmetics
@@ -757,21 +927,21 @@ int8shr(PG_FUNCTION_ARGS)
Datum
int48(PG_FUNCTION_ARGS)
{
- int32 val = PG_GETARG_INT32(0);
+ int32 arg = PG_GETARG_INT32(0);
- PG_RETURN_INT64((int64) val);
+ PG_RETURN_INT64((int64) arg);
}
Datum
int84(PG_FUNCTION_ARGS)
{
- int64 val = PG_GETARG_INT64(0);
+ int64 arg = PG_GETARG_INT64(0);
int32 result;
- result = (int32) val;
+ result = (int32) arg;
/* Test for overflow by reverse-conversion. */
- if ((int64) result != val)
+ if ((int64) result != arg)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range")));
@@ -782,24 +952,24 @@ int84(PG_FUNCTION_ARGS)
Datum
int28(PG_FUNCTION_ARGS)
{
- int16 val = PG_GETARG_INT16(0);
+ int16 arg = PG_GETARG_INT16(0);
- PG_RETURN_INT64((int64) val);
+ PG_RETURN_INT64((int64) arg);
}
Datum
int82(PG_FUNCTION_ARGS)
{
- int64 val = PG_GETARG_INT64(0);
+ int64 arg = PG_GETARG_INT64(0);
int16 result;
- result = (int16) val;
+ result = (int16) arg;
/* Test for overflow by reverse-conversion. */
- if ((int64) result != val)
+ if ((int64) result != arg)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("smallint out of range")));
PG_RETURN_INT16(result);
}
@@ -807,10 +977,10 @@ int82(PG_FUNCTION_ARGS)
Datum
i8tod(PG_FUNCTION_ARGS)
{
- int64 val = PG_GETARG_INT64(0);
+ int64 arg = PG_GETARG_INT64(0);
float8 result;
- result = val;
+ result = arg;
PG_RETURN_FLOAT8(result);
}
@@ -821,23 +991,23 @@ i8tod(PG_FUNCTION_ARGS)
Datum
dtoi8(PG_FUNCTION_ARGS)
{
- float8 val = PG_GETARG_FLOAT8(0);
+ float8 arg = PG_GETARG_FLOAT8(0);
int64 result;
- /* Round val to nearest integer (but it's still in float form) */
- val = rint(val);
+ /* 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) val;
+ result = (int64) arg;
- if ((float8) result != val)
+ if ((float8) result != arg)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("bigint out of range")));
PG_RETURN_INT64(result);
}
@@ -845,10 +1015,10 @@ dtoi8(PG_FUNCTION_ARGS)
Datum
i8tof(PG_FUNCTION_ARGS)
{
- int64 val = PG_GETARG_INT64(0);
+ int64 arg = PG_GETARG_INT64(0);
float4 result;
- result = val;
+ result = arg;
PG_RETURN_FLOAT4(result);
}
@@ -859,24 +1029,24 @@ i8tof(PG_FUNCTION_ARGS)
Datum
ftoi8(PG_FUNCTION_ARGS)
{
- float4 val = PG_GETARG_FLOAT4(0);
+ float4 arg = PG_GETARG_FLOAT4(0);
int64 result;
- float8 dval;
+ float8 darg;
- /* Round val to nearest integer (but it's still in float form) */
- dval = rint(val);
+ /* 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) dval;
+ result = (int64) darg;
- if ((float8) result != dval)
+ if ((float8) result != darg)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("bigint out of range")));
PG_RETURN_INT64(result);
}
@@ -884,13 +1054,13 @@ ftoi8(PG_FUNCTION_ARGS)
Datum
i8tooid(PG_FUNCTION_ARGS)
{
- int64 val = PG_GETARG_INT64(0);
+ int64 arg = PG_GETARG_INT64(0);
Oid result;
- result = (Oid) val;
+ result = (Oid) arg;
/* Test for overflow by reverse-conversion. */
- if ((int64) result != val)
+ if ((int64) result != arg)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("OID out of range")));
@@ -901,9 +1071,9 @@ i8tooid(PG_FUNCTION_ARGS)
Datum
oidtoi8(PG_FUNCTION_ARGS)
{
- Oid val = PG_GETARG_OID(0);
+ Oid arg = PG_GETARG_OID(0);
- PG_RETURN_INT64((int64) val);
+ PG_RETURN_INT64((int64) arg);
}
Datum
@@ -929,13 +1099,13 @@ text_int8(PG_FUNCTION_ARGS)
Datum
int8_text(PG_FUNCTION_ARGS)
{
- /* val is int64, but easier to leave it as Datum */
- Datum val = PG_GETARG_DATUM(0);
+ /* arg is int64, but easier to leave it as Datum */
+ Datum arg = PG_GETARG_DATUM(0);
char *s;
int len;
text *result;
- s = DatumGetCString(DirectFunctionCall1(int8out, val));
+ s = DatumGetCString(DirectFunctionCall1(int8out, arg));
len = strlen(s);
result = (text *) palloc(VARHDRSZ + len);
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 9c8abfb365..f99fb89715 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
* Copyright (c) 1998-2004, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.79 2004/08/30 02:54:39 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.80 2004/10/04 14:42:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1826,7 +1826,7 @@ numeric_int8(PG_FUNCTION_ARGS)
if (NUMERIC_IS_NAN(num))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cannot convert NaN to integer")));
+ errmsg("cannot convert NaN to bigint")));
/* Convert to variable format and thence to int8 */
init_var(&x);
@@ -1835,7 +1835,7 @@ numeric_int8(PG_FUNCTION_ARGS)
if (!numericvar_to_int8(&x, &result))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("bigint out of range")));
free_var(&x);
@@ -1874,7 +1874,7 @@ numeric_int2(PG_FUNCTION_ARGS)
if (NUMERIC_IS_NAN(num))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- errmsg("cannot convert NaN to integer")));
+ errmsg("cannot convert NaN to smallint")));
/* Convert to variable format and thence to int8 */
init_var(&x);
@@ -1883,7 +1883,7 @@ numeric_int2(PG_FUNCTION_ARGS)
if (!numericvar_to_int8(&x, &val))
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("smallint out of range")));
free_var(&x);
@@ -1894,7 +1894,7 @@ numeric_int2(PG_FUNCTION_ARGS)
if ((int64) result != val)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("smallint out of range")));
PG_RETURN_INT16(result);
}
diff --git a/src/backend/utils/adt/numutils.c b/src/backend/utils/adt/numutils.c
index 100f38d593..a4d18417c2 100644
--- a/src/backend/utils/adt/numutils.c
+++ b/src/backend/utils/adt/numutils.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/numutils.c,v 1.65 2004/08/29 05:06:49 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/numutils.c,v 1.66 2004/10/04 14:42:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -114,7 +114,7 @@ pg_atoi(char *s, int size, int c)
if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("value \"%s\" is out of range for type shortint", s)));
+ errmsg("value \"%s\" is out of range for type smallint", s)));
break;
case sizeof(int8):
if (errno == ERANGE || l < SCHAR_MIN || l > SCHAR_MAX)
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index b9f6a296b2..e65614a4aa 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.42 2004/08/29 05:06:49 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/utils/adt/varbit.c,v 1.43 2004/10/04 14:42:46 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1310,7 +1310,7 @@ bittoint8(PG_FUNCTION_ARGS)
if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
- errmsg("integer out of range")));
+ errmsg("bigint out of range")));
result = 0;
for (r = VARBITS(arg); r < VARBITEND(arg); r++)
diff --git a/src/test/regress/expected/int2.out b/src/test/regress/expected/int2.out
index 64e5bf58a8..f72aeb278a 100644
--- a/src/test/regress/expected/int2.out
+++ b/src/test/regress/expected/int2.out
@@ -14,7 +14,7 @@ INSERT INTO INT2_TBL(f1) VALUES ('32767');
INSERT INTO INT2_TBL(f1) VALUES ('-32767');
-- bad input values -- should give errors
INSERT INTO INT2_TBL(f1) VALUES ('100000');
-ERROR: value "100000" is out of range for type shortint
+ERROR: value "100000" is out of range for type smallint
INSERT INTO INT2_TBL(f1) VALUES ('asdf');
ERROR: invalid input syntax for integer: "asdf"
INSERT INTO INT2_TBL(f1) VALUES (' ');
@@ -144,14 +144,15 @@ SELECT '' AS three, i.* FROM INT2_TBL i WHERE (i.f1 % int4 '2') = int2 '0';
(3 rows)
SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT2_TBL i;
- five | f1 | x
-------+--------+-------
- | 0 | 0
- | 1234 | 2468
- | -1234 | -2468
- | 32767 | -2
- | -32767 | 2
-(5 rows)
+ERROR: smallint out of range
+SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT2_TBL i
+WHERE abs(f1) < 16384;
+ five | f1 | x
+------+-------+-------
+ | 0 | 0
+ | 1234 | 2468
+ | -1234 | -2468
+(3 rows)
SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT2_TBL i;
five | f1 | x
@@ -164,14 +165,16 @@ SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT2_TBL i;
(5 rows)
SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT2_TBL i;
+ERROR: smallint out of range
+SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT2_TBL i
+WHERE f1 < 32766;
five | f1 | x
------+--------+--------
| 0 | 2
| 1234 | 1236
| -1234 | -1232
- | 32767 | -32767
| -32767 | -32765
-(5 rows)
+(4 rows)
SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT2_TBL i;
five | f1 | x
@@ -184,14 +187,16 @@ SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT2_TBL i;
(5 rows)
SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT2_TBL i;
- five | f1 | x
-------+--------+-------
- | 0 | -2
- | 1234 | 1232
- | -1234 | -1236
- | 32767 | 32765
- | -32767 | 32767
-(5 rows)
+ERROR: smallint out of range
+SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT2_TBL i
+WHERE f1 > -32767;
+ five | f1 | x
+------+-------+-------
+ | 0 | -2
+ | 1234 | 1232
+ | -1234 | -1236
+ | 32767 | 32765
+(4 rows)
SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT2_TBL i;
five | f1 | x
diff --git a/src/test/regress/expected/int4.out b/src/test/regress/expected/int4.out
index e5d930e31e..0e6049f29a 100644
--- a/src/test/regress/expected/int4.out
+++ b/src/test/regress/expected/int4.out
@@ -144,64 +144,74 @@ SELECT '' AS three, i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0';
(3 rows)
SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i;
- five | f1 | x
-------+-------------+---------
- | 0 | 0
- | 123456 | 246912
- | -123456 | -246912
- | 2147483647 | -2
- | -2147483647 | 2
-(5 rows)
+ERROR: integer out of range
+SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i
+WHERE abs(f1) < 1073741824;
+ five | f1 | x
+------+---------+---------
+ | 0 | 0
+ | 123456 | 246912
+ | -123456 | -246912
+(3 rows)
SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i;
- five | f1 | x
-------+-------------+---------
- | 0 | 0
- | 123456 | 246912
- | -123456 | -246912
- | 2147483647 | -2
- | -2147483647 | 2
-(5 rows)
+ERROR: integer out of range
+SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i
+WHERE abs(f1) < 1073741824;
+ five | f1 | x
+------+---------+---------
+ | 0 | 0
+ | 123456 | 246912
+ | -123456 | -246912
+(3 rows)
SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i;
+ERROR: integer out of range
+SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i
+WHERE f1 < 2147483646;
five | f1 | x
------+-------------+-------------
| 0 | 2
| 123456 | 123458
| -123456 | -123454
- | 2147483647 | -2147483647
| -2147483647 | -2147483645
-(5 rows)
+(4 rows)
SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i;
+ERROR: integer out of range
+SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i
+WHERE f1 < 2147483646;
five | f1 | x
------+-------------+-------------
| 0 | 2
| 123456 | 123458
| -123456 | -123454
- | 2147483647 | -2147483647
| -2147483647 | -2147483645
-(5 rows)
+(4 rows)
SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i;
- five | f1 | x
-------+-------------+------------
- | 0 | -2
- | 123456 | 123454
- | -123456 | -123458
- | 2147483647 | 2147483645
- | -2147483647 | 2147483647
-(5 rows)
+ERROR: integer out of range
+SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i
+WHERE f1 > -2147483647;
+ five | f1 | x
+------+------------+------------
+ | 0 | -2
+ | 123456 | 123454
+ | -123456 | -123458
+ | 2147483647 | 2147483645
+(4 rows)
SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i;
- five | f1 | x
-------+-------------+------------
- | 0 | -2
- | 123456 | 123454
- | -123456 | -123458
- | 2147483647 | 2147483645
- | -2147483647 | 2147483647
-(5 rows)
+ERROR: integer out of range
+SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i
+WHERE f1 > -2147483647;
+ five | f1 | x
+------+------------+------------
+ | 0 | -2
+ | 123456 | 123454
+ | -123456 | -123458
+ | 2147483647 | 2147483645
+(4 rows)
SELECT '' AS five, i.f1, i.f1 / int2 '2' AS x FROM INT4_TBL i;
five | f1 | x
diff --git a/src/test/regress/expected/int8-exp-three-digits-win32.out b/src/test/regress/expected/int8-exp-three-digits-win32.out
deleted file mode 100644
index c766ee5298..0000000000
--- a/src/test/regress/expected/int8-exp-three-digits-win32.out
+++ /dev/null
@@ -1,300 +0,0 @@
---
--- INT8
--- Test int8 64-bit integers.
---
-CREATE TABLE INT8_TBL(q1 int8, q2 int8);
-INSERT INTO INT8_TBL VALUES('123','456');
-INSERT INTO INT8_TBL VALUES('123','4567890123456789');
-INSERT INTO INT8_TBL VALUES('4567890123456789','123');
-INSERT INTO INT8_TBL VALUES('4567890123456789','4567890123456789');
-INSERT INTO INT8_TBL VALUES('4567890123456789','-4567890123456789');
--- bad inputs
-INSERT INTO INT8_TBL(q1) VALUES (' ');
-ERROR: invalid input syntax for type bigint: " "
-INSERT INTO INT8_TBL(q1) VALUES ('xxx');
-ERROR: invalid input syntax for type bigint: "xxx"
-INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485');
-ERROR: integer out of range
-INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934');
-ERROR: integer out of range
-INSERT INTO INT8_TBL(q1) VALUES ('- 123');
-ERROR: invalid input syntax for type bigint: "- 123"
-INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
-ERROR: invalid input syntax for type bigint: " 345 5"
-INSERT INTO INT8_TBL(q1) VALUES ('');
-ERROR: invalid input syntax for type bigint: ""
-SELECT * FROM INT8_TBL;
- q1 | q2
-------------------+-------------------
- 123 | 456
- 123 | 4567890123456789
- 4567890123456789 | 123
- 4567890123456789 | 4567890123456789
- 4567890123456789 | -4567890123456789
-(5 rows)
-
-SELECT '' AS five, q1 AS plus, -q1 AS minus FROM INT8_TBL;
- five | plus | minus
-------+------------------+-------------------
- | 123 | -123
- | 123 | -123
- | 4567890123456789 | -4567890123456789
- | 4567890123456789 | -4567890123456789
- | 4567890123456789 | -4567890123456789
-(5 rows)
-
-SELECT '' AS five, q1, q2, q1 + q2 AS plus FROM INT8_TBL;
- five | q1 | q2 | plus
-------+------------------+-------------------+------------------
- | 123 | 456 | 579
- | 123 | 4567890123456789 | 4567890123456912
- | 4567890123456789 | 123 | 4567890123456912
- | 4567890123456789 | 4567890123456789 | 9135780246913578
- | 4567890123456789 | -4567890123456789 | 0
-(5 rows)
-
-SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL;
- five | q1 | q2 | minus
-------+------------------+-------------------+-------------------
- | 123 | 456 | -333
- | 123 | 4567890123456789 | -4567890123456666
- | 4567890123456789 | 123 | 4567890123456666
- | 4567890123456789 | 4567890123456789 | 0
- | 4567890123456789 | -4567890123456789 | 9135780246913578
-(5 rows)
-
-SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL
- WHERE q1 < 1000 or (q2 > 0 and q2 < 1000);
- three | q1 | q2 | multiply
--------+------------------+------------------+--------------------
- | 123 | 456 | 56088
- | 123 | 4567890123456789 | 561850485185185047
- | 4567890123456789 | 123 | 561850485185185047
-(3 rows)
-
-SELECT '' AS five, q1, q2, q1 / q2 AS divide FROM INT8_TBL;
- five | q1 | q2 | divide
-------+------------------+-------------------+----------------
- | 123 | 456 | 0
- | 123 | 4567890123456789 | 0
- | 4567890123456789 | 123 | 37137318076884
- | 4567890123456789 | 4567890123456789 | 1
- | 4567890123456789 | -4567890123456789 | -1
-(5 rows)
-
-SELECT '' AS five, q1, float8(q1) FROM INT8_TBL;
- five | q1 | float8
-------+------------------+-----------------------
- | 123 | 123
- | 123 | 123
- | 4567890123456789 | 4.56789012345679e+015
- | 4567890123456789 | 4.56789012345679e+015
- | 4567890123456789 | 4.56789012345679e+015
-(5 rows)
-
-SELECT '' AS five, q2, float8(q2) FROM INT8_TBL;
- five | q2 | float8
-------+-------------------+------------------------
- | 456 | 456
- | 4567890123456789 | 4.56789012345679e+015
- | 123 | 123
- | 4567890123456789 | 4.56789012345679e+015
- | -4567890123456789 | -4.56789012345679e+015
-(5 rows)
-
-SELECT '' AS five, 2 * q1 AS "twice int4" FROM INT8_TBL;
- five | twice int4
-------+------------------
- | 246
- | 246
- | 9135780246913578
- | 9135780246913578
- | 9135780246913578
-(5 rows)
-
-SELECT '' AS five, q1 * 2 AS "twice int4" FROM INT8_TBL;
- five | twice int4
-------+------------------
- | 246
- | 246
- | 9135780246913578
- | 9135780246913578
- | 9135780246913578
-(5 rows)
-
--- TO_CHAR()
---
-SELECT '' AS to_char_1, to_char(q1, '9G999G999G999G999G999'), to_char(q2, '9,999,999,999,999,999')
- FROM INT8_TBL;
- to_char_1 | to_char | to_char
------------+------------------------+------------------------
- | 123 | 456
- | 123 | 4,567,890,123,456,789
- | 4,567,890,123,456,789 | 123
- | 4,567,890,123,456,789 | 4,567,890,123,456,789
- | 4,567,890,123,456,789 | -4,567,890,123,456,789
-(5 rows)
-
-SELECT '' AS to_char_2, to_char(q1, '9G999G999G999G999G999D999G999'), to_char(q2, '9,999,999,999,999,999.999,999')
- FROM INT8_TBL;
- to_char_2 | to_char | to_char
------------+--------------------------------+--------------------------------
- | 123.000,000 | 456.000,000
- | 123.000,000 | 4,567,890,123,456,789.000,000
- | 4,567,890,123,456,789.000,000 | 123.000,000
- | 4,567,890,123,456,789.000,000 | 4,567,890,123,456,789.000,000
- | 4,567,890,123,456,789.000,000 | -4,567,890,123,456,789.000,000
-(5 rows)
-
-SELECT '' AS to_char_3, to_char( (q1 * -1), '9999999999999999PR'), to_char( (q2 * -1), '9999999999999999.999PR')
- FROM INT8_TBL;
- to_char_3 | to_char | to_char
------------+--------------------+------------------------
- | <123> | <456.000>
- | <123> | <4567890123456789.000>
- | <4567890123456789> | <123.000>
- | <4567890123456789> | <4567890123456789.000>
- | <4567890123456789> | 4567890123456789.000
-(5 rows)
-
-SELECT '' AS to_char_4, to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 * -1), 'S9999999999999999')
- FROM INT8_TBL;
- to_char_4 | to_char | to_char
------------+-------------------+-------------------
- | 123- | -456
- | 123- | -4567890123456789
- | 4567890123456789- | -123
- | 4567890123456789- | -4567890123456789
- | 4567890123456789- | +4567890123456789
-(5 rows)
-
-SELECT '' AS to_char_5, to_char(q2, 'MI9999999999999999') FROM INT8_TBL;
- to_char_5 | to_char
------------+-------------------
- | 456
- | 4567890123456789
- | 123
- | 4567890123456789
- | -4567890123456789
-(5 rows)
-
-SELECT '' AS to_char_6, to_char(q2, 'FMS9999999999999999') FROM INT8_TBL;
- to_char_6 | to_char
------------+-------------------
- | +456
- | +4567890123456789
- | +123
- | +4567890123456789
- | -4567890123456789
-(5 rows)
-
-SELECT '' AS to_char_7, to_char(q2, 'FM9999999999999999THPR') FROM INT8_TBL;
- to_char_7 | to_char
------------+--------------------
- | 456TH
- | 4567890123456789TH
- | 123RD
- | 4567890123456789TH
- | <4567890123456789>
-(5 rows)
-
-SELECT '' AS to_char_8, to_char(q2, 'SG9999999999999999th') FROM INT8_TBL;
- to_char_8 | to_char
------------+---------------------
- | + 456th
- | +4567890123456789th
- | + 123rd
- | +4567890123456789th
- | -4567890123456789
-(5 rows)
-
-SELECT '' AS to_char_9, to_char(q2, '0999999999999999') FROM INT8_TBL;
- to_char_9 | to_char
------------+-------------------
- | 0000000000000456
- | 4567890123456789
- | 0000000000000123
- | 4567890123456789
- | -4567890123456789
-(5 rows)
-
-SELECT '' AS to_char_10, to_char(q2, 'S0999999999999999') FROM INT8_TBL;
- to_char_10 | to_char
-------------+-------------------
- | +0000000000000456
- | +4567890123456789
- | +0000000000000123
- | +4567890123456789
- | -4567890123456789
-(5 rows)
-
-SELECT '' AS to_char_11, to_char(q2, 'FM0999999999999999') FROM INT8_TBL;
- to_char_11 | to_char
-------------+-------------------
- | 0000000000000456
- | 4567890123456789
- | 0000000000000123
- | 4567890123456789
- | -4567890123456789
-(5 rows)
-
-SELECT '' AS to_char_12, to_char(q2, 'FM9999999999999999.000') FROM INT8_TBL;
- to_char_12 | to_char
-------------+-----------------------
- | 456.000
- | 4567890123456789.000
- | 123.000
- | 4567890123456789.000
- | -4567890123456789.000
-(5 rows)
-
-SELECT '' AS to_char_13, to_char(q2, 'L9999999999999999.000') FROM INT8_TBL;
- to_char_13 | to_char
-------------+------------------------
- | 456.000
- | 4567890123456789.000
- | 123.000
- | 4567890123456789.000
- | -4567890123456789.000
-(5 rows)
-
-SELECT '' AS to_char_14, to_char(q2, 'FM9999999999999999.999') FROM INT8_TBL;
- to_char_14 | to_char
-------------+--------------------
- | 456.
- | 4567890123456789.
- | 123.
- | 4567890123456789.
- | -4567890123456789.
-(5 rows)
-
-SELECT '' AS to_char_15, to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9') FROM INT8_TBL;
- to_char_15 | to_char
-------------+-------------------------------------------
- | +4 5 6 . 0 0 0
- | +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
- | +1 2 3 . 0 0 0
- | +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
- | -4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
-(5 rows)
-
-SELECT '' AS to_char_16, to_char(q2, '99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL;
- to_char_16 | to_char
-------------+-----------------------------------------------------------
- | text 9999 "text between quote marks" 456
- | 45678 text 9012 9999 345 "text between quote marks" 6789
- | text 9999 "text between quote marks" 123
- | 45678 text 9012 9999 345 "text between quote marks" 6789
- | -45678 text 9012 9999 345 "text between quote marks" 6789
-(5 rows)
-
-SELECT '' AS to_char_17, to_char(q2, '999999SG9999999999') FROM INT8_TBL;
- to_char_17 | to_char
-------------+-------------------
- | + 456
- | 456789+0123456789
- | + 123
- | 456789+0123456789
- | 456789-0123456789
-(5 rows)
-
diff --git a/src/test/regress/expected/int8-exp-three-digits.out b/src/test/regress/expected/int8-exp-three-digits.out
index e1eb64792c..5e6bee8cc7 100644
--- a/src/test/regress/expected/int8-exp-three-digits.out
+++ b/src/test/regress/expected/int8-exp-three-digits.out
@@ -3,11 +3,26 @@
-- Test int8 64-bit integers.
--
CREATE TABLE INT8_TBL(q1 int8, q2 int8);
-INSERT INTO INT8_TBL VALUES('123','456');
-INSERT INTO INT8_TBL VALUES('123','4567890123456789');
+INSERT INTO INT8_TBL VALUES(' 123 ',' 456');
+INSERT INTO INT8_TBL VALUES('123 ','4567890123456789');
INSERT INTO INT8_TBL VALUES('4567890123456789','123');
INSERT INTO INT8_TBL VALUES('4567890123456789','4567890123456789');
INSERT INTO INT8_TBL VALUES('4567890123456789','-4567890123456789');
+-- bad inputs
+INSERT INTO INT8_TBL(q1) VALUES (' ');
+ERROR: invalid input syntax for integer: " "
+INSERT INTO INT8_TBL(q1) VALUES ('xxx');
+ERROR: invalid input syntax for integer: "xxx"
+INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485');
+ERROR: value "3908203590239580293850293850329485" is out of range for type bigint
+INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934');
+ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint
+INSERT INTO INT8_TBL(q1) VALUES ('- 123');
+ERROR: invalid input syntax for integer: "- 123"
+INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
+ERROR: invalid input syntax for integer: " 345 5"
+INSERT INTO INT8_TBL(q1) VALUES ('');
+ERROR: invalid input syntax for integer: ""
SELECT * FROM INT8_TBL;
q1 | q2
------------------+-------------------
@@ -48,6 +63,8 @@ SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL;
| 4567890123456789 | -4567890123456789 | 9135780246913578
(5 rows)
+SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL;
+ERROR: bigint out of range
SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL
WHERE q1 < 1000 or (q2 > 0 and q2 < 1000);
three | q1 | q2 | multiply
@@ -139,7 +156,7 @@ SELECT '' AS to_char_3, to_char( (q1 * -1), '9999999999999999PR'), to_char( (q2
| <123> | <4567890123456789.000>
| <4567890123456789> | <123.000>
| <4567890123456789> | <4567890123456789.000>
- | <4567890123456789> | 4567890123456789.000
+ | <4567890123456789> | 4567890123456789.000
(5 rows)
SELECT '' AS to_char_4, to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 * -1), 'S9999999999999999')
@@ -154,12 +171,12 @@ SELECT '' AS to_char_4, to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 *
(5 rows)
SELECT '' AS to_char_5, to_char(q2, 'MI9999999999999999') FROM INT8_TBL;
- to_char_5 | to_char
------------+--------------------
- | 456
- | 4567890123456789
- | 123
- | 4567890123456789
+ to_char_5 | to_char
+-----------+-------------------
+ | 456
+ | 4567890123456789
+ | 123
+ | 4567890123456789
| -4567890123456789
(5 rows)
@@ -256,11 +273,11 @@ SELECT '' AS to_char_14, to_char(q2, 'FM9999999999999999.999') FROM INT8_TBL;
SELECT '' AS to_char_15, to_char(q2, 'S 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 . 9 9 9') FROM INT8_TBL;
to_char_15 | to_char
------------+-------------------------------------------
- | +4 5 6 . 0 0 0
- | + 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
- | +1 2 3 . 0 0 0
- | + 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
- | - 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
+ | +4 5 6 . 0 0 0
+ | +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
+ | +1 2 3 . 0 0 0
+ | +4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
+ | -4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 . 0 0 0
(5 rows)
SELECT '' AS to_char_16, to_char(q2, '99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL;
diff --git a/src/test/regress/expected/int8.out b/src/test/regress/expected/int8.out
index 7172cc1071..164285dd65 100644
--- a/src/test/regress/expected/int8.out
+++ b/src/test/regress/expected/int8.out
@@ -10,19 +10,19 @@ INSERT INTO INT8_TBL VALUES('4567890123456789','4567890123456789');
INSERT INTO INT8_TBL VALUES('4567890123456789','-4567890123456789');
-- bad inputs
INSERT INTO INT8_TBL(q1) VALUES (' ');
-ERROR: invalid input syntax for type bigint: " "
+ERROR: invalid input syntax for integer: " "
INSERT INTO INT8_TBL(q1) VALUES ('xxx');
-ERROR: invalid input syntax for type bigint: "xxx"
+ERROR: invalid input syntax for integer: "xxx"
INSERT INTO INT8_TBL(q1) VALUES ('3908203590239580293850293850329485');
-ERROR: integer out of range
+ERROR: value "3908203590239580293850293850329485" is out of range for type bigint
INSERT INTO INT8_TBL(q1) VALUES ('-1204982019841029840928340329840934');
-ERROR: integer out of range
+ERROR: value "-1204982019841029840928340329840934" is out of range for type bigint
INSERT INTO INT8_TBL(q1) VALUES ('- 123');
-ERROR: invalid input syntax for type bigint: "- 123"
+ERROR: invalid input syntax for integer: "- 123"
INSERT INTO INT8_TBL(q1) VALUES (' 345 5');
-ERROR: invalid input syntax for type bigint: " 345 5"
+ERROR: invalid input syntax for integer: " 345 5"
INSERT INTO INT8_TBL(q1) VALUES ('');
-ERROR: invalid input syntax for type bigint: ""
+ERROR: invalid input syntax for integer: ""
SELECT * FROM INT8_TBL;
q1 | q2
------------------+-------------------
@@ -63,6 +63,8 @@ SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL;
| 4567890123456789 | -4567890123456789 | 9135780246913578
(5 rows)
+SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL;
+ERROR: bigint out of range
SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL
WHERE q1 < 1000 or (q2 > 0 and q2 < 1000);
three | q1 | q2 | multiply
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index fb80fb0a50..07e727de48 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -146,7 +146,8 @@ SELECT '' AS five, f1 AS "Correlated Field"
--
SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field"
FROM SUBSELECT_TBL ss
- WHERE f1 NOT IN (SELECT f1+1 FROM INT4_TBL WHERE f1 != ss.f1);
+ WHERE f1 NOT IN (SELECT f1+1 FROM INT4_TBL
+ WHERE f1 != ss.f1 AND f1 < 2147483647);
eight | Correlated Field | Second Field
-------+------------------+--------------
| 2 | 4
diff --git a/src/test/regress/resultmap b/src/test/regress/resultmap
index 313eca30e9..a54c7fe7ba 100644
--- a/src/test/regress/resultmap
+++ b/src/test/regress/resultmap
@@ -7,4 +7,4 @@ float8/.*-qnx=float8-exp-three-digits
float8/i.86-pc-mingw32=float8-exp-three-digits-win32
float8/i.86-pc-cygwin=float8-small-is-zero
int8/.*-qnx=int8-exp-three-digits
-int8/i.86-pc-mingw32=int8-exp-three-digits-win32
+int8/i.86-pc-mingw32=int8-exp-three-digits
diff --git a/src/test/regress/sql/int2.sql b/src/test/regress/sql/int2.sql
index e42b4236fd..81bff55712 100644
--- a/src/test/regress/sql/int2.sql
+++ b/src/test/regress/sql/int2.sql
@@ -63,14 +63,23 @@ SELECT '' AS three, i.* FROM INT2_TBL i WHERE (i.f1 % int4 '2') = int2 '0';
SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT2_TBL i;
+SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT2_TBL i
+WHERE abs(f1) < 16384;
+
SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT2_TBL i;
SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT2_TBL i;
+SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT2_TBL i
+WHERE f1 < 32766;
+
SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT2_TBL i;
SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT2_TBL i;
+SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT2_TBL i
+WHERE f1 > -32767;
+
SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT2_TBL i;
SELECT '' AS five, i.f1, i.f1 / int2 '2' AS x FROM INT2_TBL i;
diff --git a/src/test/regress/sql/int4.sql b/src/test/regress/sql/int4.sql
index 85b22ccd0a..b4c3929d09 100644
--- a/src/test/regress/sql/int4.sql
+++ b/src/test/regress/sql/int4.sql
@@ -63,16 +63,34 @@ SELECT '' AS three, i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0';
SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i;
+SELECT '' AS five, i.f1, i.f1 * int2 '2' AS x FROM INT4_TBL i
+WHERE abs(f1) < 1073741824;
+
SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i;
+SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT4_TBL i
+WHERE abs(f1) < 1073741824;
+
SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i;
+SELECT '' AS five, i.f1, i.f1 + int2 '2' AS x FROM INT4_TBL i
+WHERE f1 < 2147483646;
+
SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i;
+SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT4_TBL i
+WHERE f1 < 2147483646;
+
SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i;
+SELECT '' AS five, i.f1, i.f1 - int2 '2' AS x FROM INT4_TBL i
+WHERE f1 > -2147483647;
+
SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i;
+SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT4_TBL i
+WHERE f1 > -2147483647;
+
SELECT '' AS five, i.f1, i.f1 / int2 '2' AS x FROM INT4_TBL i;
SELECT '' AS five, i.f1, i.f1 / int4 '2' AS x FROM INT4_TBL i;
diff --git a/src/test/regress/sql/int8.sql b/src/test/regress/sql/int8.sql
index 98b1606430..ec7766219d 100644
--- a/src/test/regress/sql/int8.sql
+++ b/src/test/regress/sql/int8.sql
@@ -25,6 +25,7 @@ SELECT '' AS five, q1 AS plus, -q1 AS minus FROM INT8_TBL;
SELECT '' AS five, q1, q2, q1 + q2 AS plus FROM INT8_TBL;
SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL;
+SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL;
SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL
WHERE q1 < 1000 or (q2 > 0 and q2 < 1000);
SELECT '' AS five, q1, q2, q1 / q2 AS divide FROM INT8_TBL;
diff --git a/src/test/regress/sql/subselect.sql b/src/test/regress/sql/subselect.sql
index be3a0a87b5..5cba9ca74d 100644
--- a/src/test/regress/sql/subselect.sql
+++ b/src/test/regress/sql/subselect.sql
@@ -71,7 +71,8 @@ SELECT '' AS five, f1 AS "Correlated Field"
SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field"
FROM SUBSELECT_TBL ss
- WHERE f1 NOT IN (SELECT f1+1 FROM INT4_TBL WHERE f1 != ss.f1);
+ WHERE f1 NOT IN (SELECT f1+1 FROM INT4_TBL
+ WHERE f1 != ss.f1 AND f1 < 2147483647);
select q1, float8(count(*)) / (select count(*) from int8_tbl)
from int8_tbl group by q1 order by q1;