Commit 4171bb86 authored by Tom Lane's avatar Tom Lane

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.
parent 24201b4b
<!-- <!--
$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"> <appendix id="release">
...@@ -256,6 +256,13 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.298 2004/10/01 02:00:43 neilc E ...@@ -256,6 +256,13 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.298 2004/10/01 02:00:43 neilc E
</para> </para>
</listitem> </listitem>
<listitem>
<para>
Overflow in integer arithmetic operations is now detected and
reported as an error.
</para>
</listitem>
<listitem> <listitem>
<para> <para>
The server now warns of empty strings passed to The server now warns of empty strings passed to
...@@ -1228,6 +1235,12 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.298 2004/10/01 02:00:43 neilc E ...@@ -1228,6 +1235,12 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.298 2004/10/01 02:00:43 neilc E
</para> </para>
</listitem> </listitem>
<listitem>
<para>
Overflow in integer arithmetic operations is now detected (Tom)
</para>
</listitem>
<listitem> <listitem>
<para> <para>
Syntax checking of array input values considerably tightened up (Joe) Syntax checking of array input values considerably tightened up (Joe)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -1147,7 +1147,7 @@ dtoi2(PG_FUNCTION_ARGS)
if ((num < SHRT_MIN) || (num > SHRT_MAX)) if ((num < SHRT_MIN) || (num > SHRT_MAX))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("smallint out of range")));
result = (int16) rint(num); result = (int16) rint(num);
PG_RETURN_INT16(result); PG_RETURN_INT16(result);
...@@ -1213,7 +1213,7 @@ ftoi2(PG_FUNCTION_ARGS) ...@@ -1213,7 +1213,7 @@ ftoi2(PG_FUNCTION_ARGS)
if ((num < SHRT_MIN) || (num > SHRT_MAX)) if ((num < SHRT_MIN) || (num > SHRT_MAX))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("smallint out of range")));
result = (int16) rint(num); result = (int16) rint(num);
PG_RETURN_INT16(result); PG_RETURN_INT16(result);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 @@ ...@@ -28,7 +28,6 @@
* Arithmetic operators: * Arithmetic operators:
* intmod * intmod
*/ */
#include "postgres.h" #include "postgres.h"
#include <ctype.h> #include <ctype.h>
...@@ -38,6 +37,7 @@ ...@@ -38,6 +37,7 @@
#include "libpq/pqformat.h" #include "libpq/pqformat.h"
#include "utils/builtins.h" #include "utils/builtins.h"
#ifndef SHRT_MAX #ifndef SHRT_MAX
#define SHRT_MAX (0x7FFF) #define SHRT_MAX (0x7FFF)
#endif #endif
...@@ -45,6 +45,8 @@ ...@@ -45,6 +45,8 @@
#define SHRT_MIN (-0x8000) #define SHRT_MIN (-0x8000)
#endif #endif
#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
typedef struct typedef struct
{ {
int32 current; int32 current;
...@@ -52,6 +54,7 @@ typedef struct ...@@ -52,6 +54,7 @@ typedef struct
int32 step; int32 step;
} generate_series_fctx; } generate_series_fctx;
/***************************************************************************** /*****************************************************************************
* USER I/O ROUTINES * * USER I/O ROUTINES *
*****************************************************************************/ *****************************************************************************/
...@@ -291,7 +294,7 @@ i4toi2(PG_FUNCTION_ARGS) ...@@ -291,7 +294,7 @@ i4toi2(PG_FUNCTION_ARGS)
if (arg1 < SHRT_MIN || arg1 > SHRT_MAX) if (arg1 < SHRT_MIN || arg1 > SHRT_MAX)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("smallint out of range")));
PG_RETURN_INT16((int16) arg1); PG_RETURN_INT16((int16) arg1);
} }
...@@ -601,8 +604,15 @@ Datum ...@@ -601,8 +604,15 @@ Datum
int4um(PG_FUNCTION_ARGS) int4um(PG_FUNCTION_ARGS)
{ {
int32 arg = PG_GETARG_INT32(0); 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 Datum
...@@ -618,8 +628,19 @@ int4pl(PG_FUNCTION_ARGS) ...@@ -618,8 +628,19 @@ int4pl(PG_FUNCTION_ARGS)
{ {
int32 arg1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1); 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 Datum
...@@ -627,8 +648,19 @@ int4mi(PG_FUNCTION_ARGS) ...@@ -627,8 +648,19 @@ int4mi(PG_FUNCTION_ARGS)
{ {
int32 arg1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1); 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 Datum
...@@ -636,8 +668,28 @@ int4mul(PG_FUNCTION_ARGS) ...@@ -636,8 +668,28 @@ int4mul(PG_FUNCTION_ARGS)
{ {
int32 arg1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1); 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 Datum
...@@ -645,29 +697,55 @@ int4div(PG_FUNCTION_ARGS) ...@@ -645,29 +697,55 @@ int4div(PG_FUNCTION_ARGS)
{ {
int32 arg1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int32 arg2 = PG_GETARG_INT32(1); int32 arg2 = PG_GETARG_INT32(1);
int32 result;
if (arg2 == 0) if (arg2 == 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("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 Datum
int4inc(PG_FUNCTION_ARGS) int4inc(PG_FUNCTION_ARGS)
{ {
int32 arg = PG_GETARG_INT32(0); 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 Datum
int2um(PG_FUNCTION_ARGS) int2um(PG_FUNCTION_ARGS)
{ {
int16 arg = PG_GETARG_INT16(0); 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 Datum
...@@ -683,8 +761,19 @@ int2pl(PG_FUNCTION_ARGS) ...@@ -683,8 +761,19 @@ int2pl(PG_FUNCTION_ARGS)
{ {
int16 arg1 = PG_GETARG_INT16(0); int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1); 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 Datum
...@@ -692,8 +781,19 @@ int2mi(PG_FUNCTION_ARGS) ...@@ -692,8 +781,19 @@ int2mi(PG_FUNCTION_ARGS)
{ {
int16 arg1 = PG_GETARG_INT16(0); int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1); 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 Datum
...@@ -701,8 +801,20 @@ int2mul(PG_FUNCTION_ARGS) ...@@ -701,8 +801,20 @@ int2mul(PG_FUNCTION_ARGS)
{ {
int16 arg1 = PG_GETARG_INT16(0); int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1); 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 Datum
...@@ -710,13 +822,24 @@ int2div(PG_FUNCTION_ARGS) ...@@ -710,13 +822,24 @@ int2div(PG_FUNCTION_ARGS)
{ {
int16 arg1 = PG_GETARG_INT16(0); int16 arg1 = PG_GETARG_INT16(0);
int16 arg2 = PG_GETARG_INT16(1); int16 arg2 = PG_GETARG_INT16(1);
int16 result;
if (arg2 == 0) if (arg2 == 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("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 Datum
...@@ -724,8 +847,19 @@ int24pl(PG_FUNCTION_ARGS) ...@@ -724,8 +847,19 @@ int24pl(PG_FUNCTION_ARGS)
{ {
int16 arg1 = PG_GETARG_INT16(0); int16 arg1 = PG_GETARG_INT16(0);
int32 arg2 = PG_GETARG_INT32(1); 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 Datum
...@@ -733,8 +867,19 @@ int24mi(PG_FUNCTION_ARGS) ...@@ -733,8 +867,19 @@ int24mi(PG_FUNCTION_ARGS)
{ {
int16 arg1 = PG_GETARG_INT16(0); int16 arg1 = PG_GETARG_INT16(0);
int32 arg2 = PG_GETARG_INT32(1); 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 Datum
...@@ -742,8 +887,25 @@ int24mul(PG_FUNCTION_ARGS) ...@@ -742,8 +887,25 @@ int24mul(PG_FUNCTION_ARGS)
{ {
int16 arg1 = PG_GETARG_INT16(0); int16 arg1 = PG_GETARG_INT16(0);
int32 arg2 = PG_GETARG_INT32(1); 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 Datum
...@@ -756,8 +918,8 @@ int24div(PG_FUNCTION_ARGS) ...@@ -756,8 +918,8 @@ int24div(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero"))); errmsg("division by zero")));
/* No overflow is possible */
PG_RETURN_INT32(arg1 / arg2); PG_RETURN_INT32((int32) arg1 / arg2);
} }
Datum Datum
...@@ -765,8 +927,19 @@ int42pl(PG_FUNCTION_ARGS) ...@@ -765,8 +927,19 @@ int42pl(PG_FUNCTION_ARGS)
{ {
int32 arg1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int16 arg2 = PG_GETARG_INT16(1); 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 Datum
...@@ -774,8 +947,19 @@ int42mi(PG_FUNCTION_ARGS) ...@@ -774,8 +947,19 @@ int42mi(PG_FUNCTION_ARGS)
{ {
int32 arg1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int16 arg2 = PG_GETARG_INT16(1); 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 Datum
...@@ -783,8 +967,25 @@ int42mul(PG_FUNCTION_ARGS) ...@@ -783,8 +967,25 @@ int42mul(PG_FUNCTION_ARGS)
{ {
int32 arg1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int16 arg2 = PG_GETARG_INT16(1); 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 Datum
...@@ -792,13 +993,24 @@ int42div(PG_FUNCTION_ARGS) ...@@ -792,13 +993,24 @@ int42div(PG_FUNCTION_ARGS)
{ {
int32 arg1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int16 arg2 = PG_GETARG_INT16(1); int16 arg2 = PG_GETARG_INT16(1);
int32 result;
if (arg2 == 0) if (arg2 == 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("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 Datum
...@@ -811,6 +1023,7 @@ int4mod(PG_FUNCTION_ARGS) ...@@ -811,6 +1023,7 @@ int4mod(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero"))); errmsg("division by zero")));
/* No overflow is possible */
PG_RETURN_INT32(arg1 % arg2); PG_RETURN_INT32(arg1 % arg2);
} }
...@@ -825,6 +1038,7 @@ int2mod(PG_FUNCTION_ARGS) ...@@ -825,6 +1038,7 @@ int2mod(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero"))); errmsg("division by zero")));
/* No overflow is possible */
PG_RETURN_INT16(arg1 % arg2); PG_RETURN_INT16(arg1 % arg2);
} }
...@@ -839,6 +1053,7 @@ int24mod(PG_FUNCTION_ARGS) ...@@ -839,6 +1053,7 @@ int24mod(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero"))); errmsg("division by zero")));
/* No overflow is possible */
PG_RETURN_INT32(arg1 % arg2); PG_RETURN_INT32(arg1 % arg2);
} }
...@@ -853,6 +1068,7 @@ int42mod(PG_FUNCTION_ARGS) ...@@ -853,6 +1068,7 @@ int42mod(PG_FUNCTION_ARGS)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero"))); errmsg("division by zero")));
/* No overflow is possible */
PG_RETURN_INT32(arg1 % arg2); PG_RETURN_INT32(arg1 % arg2);
} }
...@@ -865,16 +1081,30 @@ Datum ...@@ -865,16 +1081,30 @@ Datum
int4abs(PG_FUNCTION_ARGS) int4abs(PG_FUNCTION_ARGS)
{ {
int32 arg1 = PG_GETARG_INT32(0); 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 Datum
int2abs(PG_FUNCTION_ARGS) int2abs(PG_FUNCTION_ARGS)
{ {
int16 arg1 = PG_GETARG_INT16(0); 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 Datum
...@@ -913,7 +1143,8 @@ int4smaller(PG_FUNCTION_ARGS) ...@@ -913,7 +1143,8 @@ int4smaller(PG_FUNCTION_ARGS)
PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2); PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
} }
/* Binary arithmetics /*
* Bit-pushing operators
* *
* int[24]and - returns arg1 & arg2 * int[24]and - returns arg1 & arg2
* int[24]or - returns arg1 | arg2 * int[24]or - returns arg1 | arg2
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 @@ ...@@ -24,6 +24,8 @@
#define MAXINT8LEN 25 #define MAXINT8LEN 25
#define SAMESIGN(a,b) (((a) < 0) == ((b) < 0))
typedef struct typedef struct
{ {
int64 current; int64 current;
...@@ -31,6 +33,7 @@ typedef struct ...@@ -31,6 +33,7 @@ typedef struct
int64 step; int64 step;
} generate_series_fctx; } generate_series_fctx;
/*********************************************************************** /***********************************************************************
** **
** Routines for 64-bit integers. ** Routines for 64-bit integers.
...@@ -67,7 +70,6 @@ scanint8(const char *str, bool errorOK, int64 *result) ...@@ -67,7 +70,6 @@ scanint8(const char *str, bool errorOK, int64 *result)
if (*ptr == '-') if (*ptr == '-')
{ {
ptr++; ptr++;
sign = -1;
/* /*
* Do an explicit check for INT64_MIN. Ugly though this is, it's * 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) ...@@ -75,12 +77,15 @@ scanint8(const char *str, bool errorOK, int64 *result)
* portably. * portably.
*/ */
#ifndef INT64_IS_BUSTED #ifndef INT64_IS_BUSTED
if (strcmp(ptr, "9223372036854775808") == 0) if (strncmp(ptr, "9223372036854775808", 19) == 0)
{ {
*result = -INT64CONST(0x7fffffffffffffff) - 1; tmp = -INT64CONST(0x7fffffffffffffff) - 1;
return true; ptr += 19;
goto gotdigits;
} }
#endif #endif
sign = -1;
} }
else if (*ptr == '+') else if (*ptr == '+')
ptr++; ptr++;
...@@ -93,7 +98,8 @@ scanint8(const char *str, bool errorOK, int64 *result) ...@@ -93,7 +98,8 @@ scanint8(const char *str, bool errorOK, int64 *result)
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("invalid input syntax for type bigint: \"%s\"", str))); errmsg("invalid input syntax for integer: \"%s\"",
str)));
} }
/* process digits */ /* process digits */
...@@ -108,11 +114,14 @@ scanint8(const char *str, bool errorOK, int64 *result) ...@@ -108,11 +114,14 @@ scanint8(const char *str, bool errorOK, int64 *result)
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (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; tmp = newtmp;
} }
gotdigits:
/* allow trailing whitespace, but not other trailing chars */ /* allow trailing whitespace, but not other trailing chars */
while (*ptr != '\0' && isspace((unsigned char) *ptr)) while (*ptr != '\0' && isspace((unsigned char) *ptr))
ptr++; ptr++;
...@@ -124,7 +133,8 @@ scanint8(const char *str, bool errorOK, int64 *result) ...@@ -124,7 +133,8 @@ scanint8(const char *str, bool errorOK, int64 *result)
else else
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), (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; *result = (sign < 0) ? -tmp : tmp;
...@@ -485,58 +495,118 @@ int28ge(PG_FUNCTION_ARGS) ...@@ -485,58 +495,118 @@ int28ge(PG_FUNCTION_ARGS)
Datum Datum
int8um(PG_FUNCTION_ARGS) 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 Datum
int8up(PG_FUNCTION_ARGS) 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 Datum
int8pl(PG_FUNCTION_ARGS) int8pl(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int64 val2 = PG_GETARG_INT64(1); 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 Datum
int8mi(PG_FUNCTION_ARGS) int8mi(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int64 val2 = PG_GETARG_INT64(1); 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 Datum
int8mul(PG_FUNCTION_ARGS) int8mul(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int64 val2 = PG_GETARG_INT64(1); 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 Datum
int8div(PG_FUNCTION_ARGS) int8div(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int64 val2 = PG_GETARG_INT64(1); int64 arg2 = PG_GETARG_INT64(1);
int64 result;
if (val2 == 0) if (arg2 == 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("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() /* int8abs()
...@@ -546,8 +616,15 @@ Datum ...@@ -546,8 +616,15 @@ Datum
int8abs(PG_FUNCTION_ARGS) int8abs(PG_FUNCTION_ARGS)
{ {
int64 arg1 = PG_GETARG_INT64(0); 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() /* int8mod()
...@@ -556,20 +633,16 @@ int8abs(PG_FUNCTION_ARGS) ...@@ -556,20 +633,16 @@ int8abs(PG_FUNCTION_ARGS)
Datum Datum
int8mod(PG_FUNCTION_ARGS) int8mod(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int64 val2 = PG_GETARG_INT64(1); int64 arg2 = PG_GETARG_INT64(1);
int64 result;
if (val2 == 0) if (arg2 == 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero"))); errmsg("division by zero")));
/* No overflow is possible */
result = val1 / val2; PG_RETURN_INT64(arg1 % arg2);
result *= val2;
result = val1 - result;
PG_RETURN_INT64(result);
} }
...@@ -577,18 +650,26 @@ Datum ...@@ -577,18 +650,26 @@ Datum
int8inc(PG_FUNCTION_ARGS) int8inc(PG_FUNCTION_ARGS)
{ {
int64 arg = PG_GETARG_INT64(0); 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 Datum
int8larger(PG_FUNCTION_ARGS) int8larger(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int64 val2 = PG_GETARG_INT64(1); int64 arg2 = PG_GETARG_INT64(1);
int64 result; int64 result;
result = ((val1 > val2) ? val1 : val2); result = ((arg1 > arg2) ? arg1 : arg2);
PG_RETURN_INT64(result); PG_RETURN_INT64(result);
} }
...@@ -596,11 +677,11 @@ int8larger(PG_FUNCTION_ARGS) ...@@ -596,11 +677,11 @@ int8larger(PG_FUNCTION_ARGS)
Datum Datum
int8smaller(PG_FUNCTION_ARGS) int8smaller(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int64 val2 = PG_GETARG_INT64(1); int64 arg2 = PG_GETARG_INT64(1);
int64 result; int64 result;
result = ((val1 < val2) ? val1 : val2); result = ((arg1 < arg2) ? arg1 : arg2);
PG_RETURN_INT64(result); PG_RETURN_INT64(result);
} }
...@@ -608,83 +689,172 @@ int8smaller(PG_FUNCTION_ARGS) ...@@ -608,83 +689,172 @@ int8smaller(PG_FUNCTION_ARGS)
Datum Datum
int84pl(PG_FUNCTION_ARGS) int84pl(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int32 val2 = PG_GETARG_INT32(1); 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 Datum
int84mi(PG_FUNCTION_ARGS) int84mi(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int32 val2 = PG_GETARG_INT32(1); 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 Datum
int84mul(PG_FUNCTION_ARGS) int84mul(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int32 val2 = PG_GETARG_INT32(1); 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 Datum
int84div(PG_FUNCTION_ARGS) int84div(PG_FUNCTION_ARGS)
{ {
int64 val1 = PG_GETARG_INT64(0); int64 arg1 = PG_GETARG_INT64(0);
int32 val2 = PG_GETARG_INT32(1); int32 arg2 = PG_GETARG_INT32(1);
int64 result;
if (val2 == 0) if (arg2 == 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("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 Datum
int48pl(PG_FUNCTION_ARGS) int48pl(PG_FUNCTION_ARGS)
{ {
int32 val1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int64 val2 = PG_GETARG_INT64(1); 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 Datum
int48mi(PG_FUNCTION_ARGS) int48mi(PG_FUNCTION_ARGS)
{ {
int32 val1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int64 val2 = PG_GETARG_INT64(1); 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 Datum
int48mul(PG_FUNCTION_ARGS) int48mul(PG_FUNCTION_ARGS)
{ {
int32 val1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int64 val2 = PG_GETARG_INT64(1); 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 Datum
int48div(PG_FUNCTION_ARGS) int48div(PG_FUNCTION_ARGS)
{ {
int32 val1 = PG_GETARG_INT32(0); int32 arg1 = PG_GETARG_INT32(0);
int64 val2 = PG_GETARG_INT64(1); int64 arg2 = PG_GETARG_INT64(1);
if (val2 == 0) if (arg2 == 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_DIVISION_BY_ZERO), (errcode(ERRCODE_DIVISION_BY_ZERO),
errmsg("division by zero"))); errmsg("division by zero")));
/* No overflow is possible */
PG_RETURN_INT64(val1 / val2); PG_RETURN_INT64((int64) arg1 / arg2);
} }
/* Binary arithmetics /* Binary arithmetics
...@@ -757,21 +927,21 @@ int8shr(PG_FUNCTION_ARGS) ...@@ -757,21 +927,21 @@ int8shr(PG_FUNCTION_ARGS)
Datum Datum
int48(PG_FUNCTION_ARGS) 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 Datum
int84(PG_FUNCTION_ARGS) int84(PG_FUNCTION_ARGS)
{ {
int64 val = PG_GETARG_INT64(0); int64 arg = PG_GETARG_INT64(0);
int32 result; int32 result;
result = (int32) val; result = (int32) arg;
/* Test for overflow by reverse-conversion. */ /* Test for overflow by reverse-conversion. */
if ((int64) result != val) if ((int64) result != arg)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("integer out of range")));
...@@ -782,24 +952,24 @@ int84(PG_FUNCTION_ARGS) ...@@ -782,24 +952,24 @@ int84(PG_FUNCTION_ARGS)
Datum Datum
int28(PG_FUNCTION_ARGS) 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 Datum
int82(PG_FUNCTION_ARGS) int82(PG_FUNCTION_ARGS)
{ {
int64 val = PG_GETARG_INT64(0); int64 arg = PG_GETARG_INT64(0);
int16 result; int16 result;
result = (int16) val; result = (int16) arg;
/* Test for overflow by reverse-conversion. */ /* Test for overflow by reverse-conversion. */
if ((int64) result != val) if ((int64) result != arg)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("smallint out of range")));
PG_RETURN_INT16(result); PG_RETURN_INT16(result);
} }
...@@ -807,10 +977,10 @@ int82(PG_FUNCTION_ARGS) ...@@ -807,10 +977,10 @@ int82(PG_FUNCTION_ARGS)
Datum Datum
i8tod(PG_FUNCTION_ARGS) i8tod(PG_FUNCTION_ARGS)
{ {
int64 val = PG_GETARG_INT64(0); int64 arg = PG_GETARG_INT64(0);
float8 result; float8 result;
result = val; result = arg;
PG_RETURN_FLOAT8(result); PG_RETURN_FLOAT8(result);
} }
...@@ -821,23 +991,23 @@ i8tod(PG_FUNCTION_ARGS) ...@@ -821,23 +991,23 @@ i8tod(PG_FUNCTION_ARGS)
Datum Datum
dtoi8(PG_FUNCTION_ARGS) dtoi8(PG_FUNCTION_ARGS)
{ {
float8 val = PG_GETARG_FLOAT8(0); float8 arg = PG_GETARG_FLOAT8(0);
int64 result; int64 result;
/* Round val to nearest integer (but it's still in float form) */ /* Round arg to nearest integer (but it's still in float form) */
val = rint(val); arg = rint(arg);
/* /*
* Does it fit in an int64? Avoid assuming that we have handy * Does it fit in an int64? Avoid assuming that we have handy
* constants defined for the range boundaries, instead test for * constants defined for the range boundaries, instead test for
* overflow by reverse-conversion. * overflow by reverse-conversion.
*/ */
result = (int64) val; result = (int64) arg;
if ((float8) result != val) if ((float8) result != arg)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("bigint out of range")));
PG_RETURN_INT64(result); PG_RETURN_INT64(result);
} }
...@@ -845,10 +1015,10 @@ dtoi8(PG_FUNCTION_ARGS) ...@@ -845,10 +1015,10 @@ dtoi8(PG_FUNCTION_ARGS)
Datum Datum
i8tof(PG_FUNCTION_ARGS) i8tof(PG_FUNCTION_ARGS)
{ {
int64 val = PG_GETARG_INT64(0); int64 arg = PG_GETARG_INT64(0);
float4 result; float4 result;
result = val; result = arg;
PG_RETURN_FLOAT4(result); PG_RETURN_FLOAT4(result);
} }
...@@ -859,24 +1029,24 @@ i8tof(PG_FUNCTION_ARGS) ...@@ -859,24 +1029,24 @@ i8tof(PG_FUNCTION_ARGS)
Datum Datum
ftoi8(PG_FUNCTION_ARGS) ftoi8(PG_FUNCTION_ARGS)
{ {
float4 val = PG_GETARG_FLOAT4(0); float4 arg = PG_GETARG_FLOAT4(0);
int64 result; int64 result;
float8 dval; float8 darg;
/* Round val to nearest integer (but it's still in float form) */ /* Round arg to nearest integer (but it's still in float form) */
dval = rint(val); darg = rint(arg);
/* /*
* Does it fit in an int64? Avoid assuming that we have handy * Does it fit in an int64? Avoid assuming that we have handy
* constants defined for the range boundaries, instead test for * constants defined for the range boundaries, instead test for
* overflow by reverse-conversion. * overflow by reverse-conversion.
*/ */
result = (int64) dval; result = (int64) darg;
if ((float8) result != dval) if ((float8) result != darg)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("bigint out of range")));
PG_RETURN_INT64(result); PG_RETURN_INT64(result);
} }
...@@ -884,13 +1054,13 @@ ftoi8(PG_FUNCTION_ARGS) ...@@ -884,13 +1054,13 @@ ftoi8(PG_FUNCTION_ARGS)
Datum Datum
i8tooid(PG_FUNCTION_ARGS) i8tooid(PG_FUNCTION_ARGS)
{ {
int64 val = PG_GETARG_INT64(0); int64 arg = PG_GETARG_INT64(0);
Oid result; Oid result;
result = (Oid) val; result = (Oid) arg;
/* Test for overflow by reverse-conversion. */ /* Test for overflow by reverse-conversion. */
if ((int64) result != val) if ((int64) result != arg)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("OID out of range"))); errmsg("OID out of range")));
...@@ -901,9 +1071,9 @@ i8tooid(PG_FUNCTION_ARGS) ...@@ -901,9 +1071,9 @@ i8tooid(PG_FUNCTION_ARGS)
Datum Datum
oidtoi8(PG_FUNCTION_ARGS) 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 Datum
...@@ -929,13 +1099,13 @@ text_int8(PG_FUNCTION_ARGS) ...@@ -929,13 +1099,13 @@ text_int8(PG_FUNCTION_ARGS)
Datum Datum
int8_text(PG_FUNCTION_ARGS) int8_text(PG_FUNCTION_ARGS)
{ {
/* val is int64, but easier to leave it as Datum */ /* arg is int64, but easier to leave it as Datum */
Datum val = PG_GETARG_DATUM(0); Datum arg = PG_GETARG_DATUM(0);
char *s; char *s;
int len; int len;
text *result; text *result;
s = DatumGetCString(DirectFunctionCall1(int8out, val)); s = DatumGetCString(DirectFunctionCall1(int8out, arg));
len = strlen(s); len = strlen(s);
result = (text *) palloc(VARHDRSZ + len); result = (text *) palloc(VARHDRSZ + len);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* Copyright (c) 1998-2004, PostgreSQL Global Development Group * Copyright (c) 1998-2004, PostgreSQL Global Development Group
* *
* IDENTIFICATION * 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) ...@@ -1826,7 +1826,7 @@ numeric_int8(PG_FUNCTION_ARGS)
if (NUMERIC_IS_NAN(num)) if (NUMERIC_IS_NAN(num))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (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 */ /* Convert to variable format and thence to int8 */
init_var(&x); init_var(&x);
...@@ -1835,7 +1835,7 @@ numeric_int8(PG_FUNCTION_ARGS) ...@@ -1835,7 +1835,7 @@ numeric_int8(PG_FUNCTION_ARGS)
if (!numericvar_to_int8(&x, &result)) if (!numericvar_to_int8(&x, &result))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("bigint out of range")));
free_var(&x); free_var(&x);
...@@ -1874,7 +1874,7 @@ numeric_int2(PG_FUNCTION_ARGS) ...@@ -1874,7 +1874,7 @@ numeric_int2(PG_FUNCTION_ARGS)
if (NUMERIC_IS_NAN(num)) if (NUMERIC_IS_NAN(num))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (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 */ /* Convert to variable format and thence to int8 */
init_var(&x); init_var(&x);
...@@ -1883,7 +1883,7 @@ numeric_int2(PG_FUNCTION_ARGS) ...@@ -1883,7 +1883,7 @@ numeric_int2(PG_FUNCTION_ARGS)
if (!numericvar_to_int8(&x, &val)) if (!numericvar_to_int8(&x, &val))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("smallint out of range")));
free_var(&x); free_var(&x);
...@@ -1894,7 +1894,7 @@ numeric_int2(PG_FUNCTION_ARGS) ...@@ -1894,7 +1894,7 @@ numeric_int2(PG_FUNCTION_ARGS)
if ((int64) result != val) if ((int64) result != val)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("smallint out of range")));
PG_RETURN_INT16(result); PG_RETURN_INT16(result);
} }
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -114,7 +114,7 @@ pg_atoi(char *s, int size, int c)
if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX) if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (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; break;
case sizeof(int8): case sizeof(int8):
if (errno == ERANGE || l < SCHAR_MIN || l > SCHAR_MAX) if (errno == ERANGE || l < SCHAR_MIN || l > SCHAR_MAX)
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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) ...@@ -1310,7 +1310,7 @@ bittoint8(PG_FUNCTION_ARGS)
if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE) if (VARBITLEN(arg) > sizeof(result) * BITS_PER_BYTE)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
errmsg("integer out of range"))); errmsg("bigint out of range")));
result = 0; result = 0;
for (r = VARBITS(arg); r < VARBITEND(arg); r++) for (r = VARBITS(arg); r < VARBITEND(arg); r++)
......
...@@ -14,7 +14,7 @@ INSERT INTO INT2_TBL(f1) VALUES ('32767'); ...@@ -14,7 +14,7 @@ INSERT INTO INT2_TBL(f1) VALUES ('32767');
INSERT INTO INT2_TBL(f1) VALUES ('-32767'); INSERT INTO INT2_TBL(f1) VALUES ('-32767');
-- bad input values -- should give errors -- bad input values -- should give errors
INSERT INTO INT2_TBL(f1) VALUES ('100000'); 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'); INSERT INTO INT2_TBL(f1) VALUES ('asdf');
ERROR: invalid input syntax for integer: "asdf" ERROR: invalid input syntax for integer: "asdf"
INSERT INTO INT2_TBL(f1) VALUES (' '); 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'; ...@@ -144,14 +144,15 @@ SELECT '' AS three, i.* FROM INT2_TBL i WHERE (i.f1 % int4 '2') = int2 '0';
(3 rows) (3 rows)
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;
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 five | f1 | x
------+--------+------- ------+-------+-------
| 0 | 0 | 0 | 0
| 1234 | 2468 | 1234 | 2468
| -1234 | -2468 | -1234 | -2468
| 32767 | -2 (3 rows)
| -32767 | 2
(5 rows)
SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT2_TBL i; SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT2_TBL i;
five | f1 | x five | f1 | x
...@@ -164,14 +165,16 @@ SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT2_TBL i; ...@@ -164,14 +165,16 @@ SELECT '' AS five, i.f1, i.f1 * int4 '2' AS x FROM INT2_TBL i;
(5 rows) (5 rows)
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;
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 five | f1 | x
------+--------+-------- ------+--------+--------
| 0 | 2 | 0 | 2
| 1234 | 1236 | 1234 | 1236
| -1234 | -1232 | -1234 | -1232
| 32767 | -32767
| -32767 | -32765 | -32767 | -32765
(5 rows) (4 rows)
SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT2_TBL i; SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT2_TBL i;
five | f1 | x five | f1 | x
...@@ -184,14 +187,16 @@ SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT2_TBL i; ...@@ -184,14 +187,16 @@ SELECT '' AS five, i.f1, i.f1 + int4 '2' AS x FROM INT2_TBL i;
(5 rows) (5 rows)
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;
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 five | f1 | x
------+--------+------- ------+-------+-------
| 0 | -2 | 0 | -2
| 1234 | 1232 | 1234 | 1232
| -1234 | -1236 | -1234 | -1236
| 32767 | 32765 | 32767 | 32765
| -32767 | 32767 (4 rows)
(5 rows)
SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT2_TBL i; SELECT '' AS five, i.f1, i.f1 - int4 '2' AS x FROM INT2_TBL i;
five | f1 | x five | f1 | x
......
...@@ -144,64 +144,74 @@ SELECT '' AS three, i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0'; ...@@ -144,64 +144,74 @@ SELECT '' AS three, i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0';
(3 rows) (3 rows)
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;
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 five | f1 | x
------+-------------+--------- ------+---------+---------
| 0 | 0 | 0 | 0
| 123456 | 246912 | 123456 | 246912
| -123456 | -246912 | -123456 | -246912
| 2147483647 | -2 (3 rows)
| -2147483647 | 2
(5 rows)
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;
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 five | f1 | x
------+-------------+--------- ------+---------+---------
| 0 | 0 | 0 | 0
| 123456 | 246912 | 123456 | 246912
| -123456 | -246912 | -123456 | -246912
| 2147483647 | -2 (3 rows)
| -2147483647 | 2
(5 rows)
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;
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 five | f1 | x
------+-------------+------------- ------+-------------+-------------
| 0 | 2 | 0 | 2
| 123456 | 123458 | 123456 | 123458
| -123456 | -123454 | -123456 | -123454
| 2147483647 | -2147483647
| -2147483647 | -2147483645 | -2147483647 | -2147483645
(5 rows) (4 rows)
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;
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 five | f1 | x
------+-------------+------------- ------+-------------+-------------
| 0 | 2 | 0 | 2
| 123456 | 123458 | 123456 | 123458
| -123456 | -123454 | -123456 | -123454
| 2147483647 | -2147483647
| -2147483647 | -2147483645 | -2147483647 | -2147483645
(5 rows) (4 rows)
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;
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 five | f1 | x
------+-------------+------------ ------+------------+------------
| 0 | -2 | 0 | -2
| 123456 | 123454 | 123456 | 123454
| -123456 | -123458 | -123456 | -123458
| 2147483647 | 2147483645 | 2147483647 | 2147483645
| -2147483647 | 2147483647 (4 rows)
(5 rows)
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;
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 five | f1 | x
------+-------------+------------ ------+------------+------------
| 0 | -2 | 0 | -2
| 123456 | 123454 | 123456 | 123454
| -123456 | -123458 | -123456 | -123458
| 2147483647 | 2147483645 | 2147483647 | 2147483645
| -2147483647 | 2147483647 (4 rows)
(5 rows)
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;
five | f1 | x five | f1 | x
......
--
-- 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)
...@@ -3,11 +3,26 @@ ...@@ -3,11 +3,26 @@
-- Test int8 64-bit integers. -- Test int8 64-bit integers.
-- --
CREATE TABLE INT8_TBL(q1 int8, q2 int8); CREATE TABLE INT8_TBL(q1 int8, q2 int8);
INSERT INTO INT8_TBL VALUES('123','456'); INSERT INTO INT8_TBL VALUES(' 123 ',' 456');
INSERT INTO INT8_TBL VALUES('123','4567890123456789'); INSERT INTO INT8_TBL VALUES('123 ','4567890123456789');
INSERT INTO INT8_TBL VALUES('4567890123456789','123'); INSERT INTO INT8_TBL VALUES('4567890123456789','123');
INSERT INTO INT8_TBL VALUES('4567890123456789','4567890123456789'); INSERT INTO INT8_TBL VALUES('4567890123456789','4567890123456789');
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; SELECT * FROM INT8_TBL;
q1 | q2 q1 | q2
------------------+------------------- ------------------+-------------------
...@@ -48,6 +63,8 @@ SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL; ...@@ -48,6 +63,8 @@ SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL;
| 4567890123456789 | -4567890123456789 | 9135780246913578 | 4567890123456789 | -4567890123456789 | 9135780246913578
(5 rows) (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 SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL
WHERE q1 < 1000 or (q2 > 0 and q2 < 1000); WHERE q1 < 1000 or (q2 > 0 and q2 < 1000);
three | q1 | q2 | multiply three | q1 | q2 | multiply
...@@ -155,7 +172,7 @@ SELECT '' AS to_char_4, to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 * ...@@ -155,7 +172,7 @@ SELECT '' AS to_char_4, to_char( (q1 * -1), '9999999999999999S'), to_char( (q2 *
SELECT '' AS to_char_5, to_char(q2, 'MI9999999999999999') FROM INT8_TBL; SELECT '' AS to_char_5, to_char(q2, 'MI9999999999999999') FROM INT8_TBL;
to_char_5 | to_char to_char_5 | to_char
-----------+-------------------- -----------+-------------------
| 456 | 456
| 4567890123456789 | 4567890123456789
| 123 | 123
...@@ -257,10 +274,10 @@ 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' ...@@ -257,10 +274,10 @@ 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'
to_char_15 | to_char to_char_15 | to_char
------------+------------------------------------------- ------------+-------------------------------------------
| +4 5 6 . 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 | +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 | +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 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) (5 rows)
SELECT '' AS to_char_16, to_char(q2, '99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL; SELECT '' AS to_char_16, to_char(q2, '99999 "text" 9999 "9999" 999 "\\"text between quote marks\\"" 9999') FROM INT8_TBL;
......
...@@ -10,19 +10,19 @@ INSERT INTO INT8_TBL VALUES('4567890123456789','4567890123456789'); ...@@ -10,19 +10,19 @@ INSERT INTO INT8_TBL VALUES('4567890123456789','4567890123456789');
INSERT INTO INT8_TBL VALUES('4567890123456789','-4567890123456789'); INSERT INTO INT8_TBL VALUES('4567890123456789','-4567890123456789');
-- bad inputs -- bad inputs
INSERT INTO INT8_TBL(q1) VALUES (' '); 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'); 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'); 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'); 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'); 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'); 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 (''); INSERT INTO INT8_TBL(q1) VALUES ('');
ERROR: invalid input syntax for type bigint: "" ERROR: invalid input syntax for integer: ""
SELECT * FROM INT8_TBL; SELECT * FROM INT8_TBL;
q1 | q2 q1 | q2
------------------+------------------- ------------------+-------------------
...@@ -63,6 +63,8 @@ SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL; ...@@ -63,6 +63,8 @@ SELECT '' AS five, q1, q2, q1 - q2 AS minus FROM INT8_TBL;
| 4567890123456789 | -4567890123456789 | 9135780246913578 | 4567890123456789 | -4567890123456789 | 9135780246913578
(5 rows) (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 SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL
WHERE q1 < 1000 or (q2 > 0 and q2 < 1000); WHERE q1 < 1000 or (q2 > 0 and q2 < 1000);
three | q1 | q2 | multiply three | q1 | q2 | multiply
......
...@@ -146,7 +146,8 @@ SELECT '' AS five, f1 AS "Correlated Field" ...@@ -146,7 +146,8 @@ SELECT '' AS five, f1 AS "Correlated Field"
-- --
SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field" SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field"
FROM SUBSELECT_TBL ss 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 eight | Correlated Field | Second Field
-------+------------------+-------------- -------+------------------+--------------
| 2 | 4 | 2 | 4
......
...@@ -7,4 +7,4 @@ float8/.*-qnx=float8-exp-three-digits ...@@ -7,4 +7,4 @@ float8/.*-qnx=float8-exp-three-digits
float8/i.86-pc-mingw32=float8-exp-three-digits-win32 float8/i.86-pc-mingw32=float8-exp-three-digits-win32
float8/i.86-pc-cygwin=float8-small-is-zero float8/i.86-pc-cygwin=float8-small-is-zero
int8/.*-qnx=int8-exp-three-digits 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
...@@ -63,14 +63,23 @@ SELECT '' AS three, i.* FROM INT2_TBL i WHERE (i.f1 % int4 '2') = int2 '0'; ...@@ -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;
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 * 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;
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 + 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;
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 - 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;
......
...@@ -63,16 +63,34 @@ SELECT '' AS three, i.* FROM INT4_TBL i WHERE (i.f1 % int4 '2') = int2 '0'; ...@@ -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;
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;
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;
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;
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;
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;
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 / int2 '2' AS x FROM INT4_TBL i;
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;
......
...@@ -25,6 +25,7 @@ SELECT '' AS five, q1 AS plus, -q1 AS minus FROM INT8_TBL; ...@@ -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 plus FROM INT8_TBL;
SELECT '' AS five, q1, q2, q1 - q2 AS minus 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 SELECT '' AS three, q1, q2, q1 * q2 AS multiply FROM INT8_TBL
WHERE q1 < 1000 or (q2 > 0 and q2 < 1000); WHERE q1 < 1000 or (q2 > 0 and q2 < 1000);
SELECT '' AS five, q1, q2, q1 / q2 AS divide FROM INT8_TBL; SELECT '' AS five, q1, q2, q1 / q2 AS divide FROM INT8_TBL;
......
...@@ -71,7 +71,8 @@ SELECT '' AS five, f1 AS "Correlated Field" ...@@ -71,7 +71,8 @@ SELECT '' AS five, f1 AS "Correlated Field"
SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field" SELECT '' AS eight, ss.f1 AS "Correlated Field", ss.f3 AS "Second Field"
FROM SUBSELECT_TBL ss 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) select q1, float8(count(*)) / (select count(*) from int8_tbl)
from int8_tbl group by q1 order by q1; from int8_tbl group by q1 order by q1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment