Add explicit tests for division by zero to all user-accessible integer
authorTom Lane
Tue, 11 Mar 2003 21:01:33 +0000 (21:01 +0000)
committerTom Lane
Tue, 11 Mar 2003 21:01:33 +0000 (21:01 +0000)
division and modulo functions, to avoid problems on OS X (which fails to
trap 0 divide at all) and Windows (which traps it in some bizarre
nonstandard fashion).  Standardize on 'division by zero' as the one true
spelling of this error message.  Add regression tests as suggested by
Neil Conway.

16 files changed:
src/backend/utils/adt/cash.c
src/backend/utils/adt/char.c
src/backend/utils/adt/float.c
src/backend/utils/adt/geo_ops.c
src/backend/utils/adt/int.c
src/backend/utils/adt/int8.c
src/backend/utils/adt/numeric.c
src/backend/utils/adt/timestamp.c
src/test/regress/expected/errors.out
src/test/regress/expected/float4-exp-three-digits.out
src/test/regress/expected/float4.out
src/test/regress/expected/float8-exp-three-digits.out
src/test/regress/expected/float8-fp-exception.out
src/test/regress/expected/float8-small-is-zero.out
src/test/regress/expected/float8.out
src/test/regress/sql/errors.sql

index c33bca654e8dd83d9bbd81225207934ade8d5758..f210f4258f05a40b2e9254c80d9e800b0df43510 100644 (file)
@@ -9,7 +9,7 @@
  * workings can be found in the book "Software Solutions in C" by
  * Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.56 2002/09/04 20:31:27 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.57 2003/03/11 21:01:33 tgl Exp $
  */
 
 #include "postgres.h"
@@ -442,7 +442,7 @@ cash_div_flt8(PG_FUNCTION_ARGS)
    Cash        result;
 
    if (f == 0.0)
-       elog(ERROR, "cash_div:  divide by 0.0 error");
+       elog(ERROR, "division by zero");
 
    result = rint(c / f);
    PG_RETURN_CASH(result);
@@ -492,7 +492,7 @@ cash_div_flt4(PG_FUNCTION_ARGS)
    Cash        result;
 
    if (f == 0.0)
-       elog(ERROR, "cash_div:  divide by 0.0 error");
+       elog(ERROR, "division by zero");
 
    result = rint(c / f);
    PG_RETURN_CASH(result);
@@ -543,7 +543,7 @@ cash_div_int4(PG_FUNCTION_ARGS)
    Cash        result;
 
    if (i == 0)
-       elog(ERROR, "cash_div_int4: divide by 0 error");
+       elog(ERROR, "division by zero");
 
    result = rint(c / i);
 
@@ -593,7 +593,7 @@ cash_div_int2(PG_FUNCTION_ARGS)
    Cash        result;
 
    if (s == 0)
-       elog(ERROR, "cash_div:  divide by 0 error");
+       elog(ERROR, "division by zero");
 
    result = rint(c / s);
    PG_RETURN_CASH(result);
index c31995fdf065e62407772af72c52af53b355fd79..0e2d400aa0d7e717eee9803931aa641585a6192f 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/char.c,v 1.33 2002/06/20 20:29:36 momjian Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/char.c,v 1.34 2003/03/11 21:01:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -150,6 +150,9 @@ chardiv(PG_FUNCTION_ARGS)
    char        arg1 = PG_GETARG_CHAR(0);
    char        arg2 = PG_GETARG_CHAR(1);
 
+   if (arg2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_CHAR((int8) arg1 / (int8) arg2);
 }
 
index c0acc554b8e132c559a84237cd0108fe351e546a..4220b4775a9a420f157867d0389bc8101a776011 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.83 2002/11/08 17:37:52 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.84 2003/03/11 21:01:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -505,7 +505,7 @@ float4div(PG_FUNCTION_ARGS)
    double      result;
 
    if (arg2 == 0.0)
-       elog(ERROR, "float4div: divide by zero error");
+       elog(ERROR, "division by zero");
 
    /* Do division in float8, then check for overflow */
    result = (float8) arg1 / (float8) arg2;
@@ -567,7 +567,7 @@ float8div(PG_FUNCTION_ARGS)
    float8      result;
 
    if (arg2 == 0.0)
-       elog(ERROR, "float8div: divide by zero error");
+       elog(ERROR, "division by zero");
 
    result = arg1 / arg2;
 
@@ -1753,7 +1753,7 @@ float48div(PG_FUNCTION_ARGS)
    float8      result;
 
    if (arg2 == 0.0)
-       elog(ERROR, "float48div: divide by zero");
+       elog(ERROR, "division by zero");
 
    result = arg1 / arg2;
    CheckFloat8Val(result);
@@ -1813,7 +1813,7 @@ float84div(PG_FUNCTION_ARGS)
    float8      result;
 
    if (arg2 == 0.0)
-       elog(ERROR, "float84div: divide by zero");
+       elog(ERROR, "division by zero");
 
    result = arg1 / arg2;
 
index 9fe40d2ccbea0a348da2544d45a9cc3c7a536cbf..d8d1f7c3afeae39b34e3b322890c23ec9fed1bd8 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.74 2003/01/21 19:44:26 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.75 2003/03/11 21:01:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3504,7 +3504,7 @@ point_div(PG_FUNCTION_ARGS)
    div = (p2->x * p2->x) + (p2->y * p2->y);
 
    if (div == 0.0)
-       elog(ERROR, "point_div:  divide by 0.0 error");
+       elog(ERROR, "division by zero");
 
    result->x = ((p1->x * p2->x) + (p1->y * p2->y)) / div;
    result->y = ((p2->x * p1->y) - (p2->y * p1->x)) / div;
index 859e78b58cb724bb2fb61d39822460727466fe2e..73687d55ec93d07b6da94d8120017b31cb354779 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.52 2002/08/22 00:01:43 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.53 2003/03/11 21:01:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -551,6 +551,9 @@ int4div(PG_FUNCTION_ARGS)
    int32       arg1 = PG_GETARG_INT32(0);
    int32       arg2 = PG_GETARG_INT32(1);
 
+   if (arg2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT32(arg1 / arg2);
 }
 
@@ -611,6 +614,9 @@ int2div(PG_FUNCTION_ARGS)
    int16       arg1 = PG_GETARG_INT16(0);
    int16       arg2 = PG_GETARG_INT16(1);
 
+   if (arg2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT16(arg1 / arg2);
 }
 
@@ -647,6 +653,9 @@ int24div(PG_FUNCTION_ARGS)
    int16       arg1 = PG_GETARG_INT16(0);
    int32       arg2 = PG_GETARG_INT32(1);
 
+   if (arg2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT32(arg1 / arg2);
 }
 
@@ -683,6 +692,9 @@ int42div(PG_FUNCTION_ARGS)
    int32       arg1 = PG_GETARG_INT32(0);
    int16       arg2 = PG_GETARG_INT16(1);
 
+   if (arg2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT32(arg1 / arg2);
 }
 
@@ -692,6 +704,9 @@ int4mod(PG_FUNCTION_ARGS)
    int32       arg1 = PG_GETARG_INT32(0);
    int32       arg2 = PG_GETARG_INT32(1);
 
+   if (arg2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT32(arg1 % arg2);
 }
 
@@ -701,6 +716,9 @@ int2mod(PG_FUNCTION_ARGS)
    int16       arg1 = PG_GETARG_INT16(0);
    int16       arg2 = PG_GETARG_INT16(1);
 
+   if (arg2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT16(arg1 % arg2);
 }
 
@@ -710,6 +728,9 @@ int24mod(PG_FUNCTION_ARGS)
    int16       arg1 = PG_GETARG_INT16(0);
    int32       arg2 = PG_GETARG_INT32(1);
 
+   if (arg2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT32(arg1 % arg2);
 }
 
@@ -719,6 +740,9 @@ int42mod(PG_FUNCTION_ARGS)
    int32       arg1 = PG_GETARG_INT32(0);
    int16       arg2 = PG_GETARG_INT16(1);
 
+   if (arg2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT32(arg1 % arg2);
 }
 
index 8a346cd8b838be5520de718356ed2d6dbf59b6e6..cf16456105842dec0ab2827e7872a20cbf88e188 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.42 2002/09/18 21:35:22 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.43 2003/03/11 21:01:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -504,6 +504,9 @@ int8div(PG_FUNCTION_ARGS)
    int64       val1 = PG_GETARG_INT64(0);
    int64       val2 = PG_GETARG_INT64(1);
 
+   if (val2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT64(val1 / val2);
 }
 
@@ -528,6 +531,9 @@ int8mod(PG_FUNCTION_ARGS)
    int64       val2 = PG_GETARG_INT64(1);
    int64       result;
 
+   if (val2 == 0)
+       elog(ERROR, "division by zero");
+
    result = val1 / val2;
    result *= val2;
    result = val1 - result;
@@ -621,6 +627,9 @@ int84div(PG_FUNCTION_ARGS)
    int64       val1 = PG_GETARG_INT64(0);
    int32       val2 = PG_GETARG_INT32(1);
 
+   if (val2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT64(val1 / val2);
 }
 
@@ -657,6 +666,9 @@ int48div(PG_FUNCTION_ARGS)
    int32       val1 = PG_GETARG_INT32(0);
    int64       val2 = PG_GETARG_INT64(1);
 
+   if (val2 == 0)
+       elog(ERROR, "division by zero");
+
    PG_RETURN_INT64(val1 / val2);
 }
 
index f1967019d53ba7802440b005165dd432084a760f..1a21500a8b088d0da36691f66a7a1afa4bef871d 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 1998 Jan Wieck
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.56 2002/10/19 02:08:17 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.57 2003/03/11 21:01:33 tgl Exp $
  *
  * ----------
  */
@@ -3266,7 +3266,7 @@ div_var(NumericVar *var1, NumericVar *var2, NumericVar *result)
     */
    ndigits_tmp = var2->ndigits + 1;
    if (ndigits_tmp == 1)
-       elog(ERROR, "division by zero on numeric");
+       elog(ERROR, "division by zero");
 
    /*
     * Determine the result sign, weight and number of digits to calculate
index d3390fd327442cddd2efdd68a6f803f22a364c2b..2764fee906a09d80fc77c6d5ee62121c6dbb2c3b 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.79 2003/02/27 21:36:58 tgl Exp $
+ *   $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.80 2003/03/11 21:01:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1869,7 +1869,7 @@ interval_div(PG_FUNCTION_ARGS)
    result = (Interval *) palloc(sizeof(Interval));
 
    if (factor == 0.0)
-       elog(ERROR, "interval_div: divide by 0.0 error");
+       elog(ERROR, "division by zero");
 
 #ifdef HAVE_INT64_TIMESTAMP
    result->month = (span->month / factor);
index 698ccc85654b1c3611b922cdef7dfa80467dc74b..6c386292176fde500cd1c8779e4c7386af3d8d62 100644 (file)
@@ -18,7 +18,7 @@ select 1;
 -- notify pg_class
 --
 --
--- RETRIEVE
+-- SELECT
  
 -- missing relation name 
 select;
@@ -54,7 +54,7 @@ ERROR:  parser: parse error at or near ";" at character 12
 delete from nonesuch;
 ERROR:  Relation "nonesuch" does not exist
 --
--- DESTROY
+-- DROP
  
 -- missing relation name (this had better not wildcard!) 
 drop table;
@@ -63,7 +63,7 @@ ERROR:  parser: parse error at or near ";" at character 11
 drop table nonesuch;
 ERROR:  table "nonesuch" does not exist
 --
--- RENAME
+-- ALTER TABLE
  
 -- relation renaming 
 -- missing relation name 
@@ -104,7 +104,7 @@ WARNING:  ROLLBACK: no transaction in progress
 end;
 WARNING:  COMMIT: no transaction in progress
 --
--- DEFINE AGGREGATE
+-- CREATE AGGREGATE
 -- sfunc/finalfunc type disagreement 
 create aggregate newavg2 (sfunc = int4pl,
              basetype = int4,
@@ -118,7 +118,7 @@ create aggregate newcnt1 (sfunc = int4inc,
              initcond = '0');
 ERROR:  Define: "basetype" unspecified
 --
--- REMOVE INDEX
+-- DROP INDEX
  
 -- missing index name 
 drop index;
@@ -130,7 +130,7 @@ ERROR:  parser: parse error at or near "314159" at character 12
 drop index nonesuch;
 ERROR:  index "nonesuch" does not exist
 --
--- REMOVE AGGREGATE
+-- DROP AGGREGATE
  
 -- missing aggregate name 
 drop aggregate;
@@ -151,7 +151,7 @@ ERROR:  RemoveAggregate: aggregate nonesuch(integer) does not exist
 drop aggregate newcnt (float4);
 ERROR:  RemoveAggregate: aggregate newcnt(real) does not exist
 --
--- REMOVE FUNCTION
+-- DROP FUNCTION
  
 -- missing function name 
 drop function ();
@@ -163,7 +163,7 @@ ERROR:  parser: parse error at or near "314159" at character 15
 drop function nonesuch();
 ERROR:  RemoveFunction: function nonesuch() does not exist
 --
--- REMOVE TYPE
+-- DROP TYPE
  
 -- missing type name 
 drop type;
@@ -237,3 +237,28 @@ ERROR:  parser: parse error at or near "instance" at character 6
 -- no such rule 
 drop rewrite rule nonesuch;
 ERROR:  parser: parse error at or near "rewrite" at character 6
+--
+-- Check that division-by-zero is properly caught.
+--
+select 1/0;
+ERROR:  division by zero
+select 1::int8/0;
+ERROR:  division by zero
+select 1/0::int8;
+ERROR:  division by zero
+select 1::int2/0;
+ERROR:  division by zero
+select 1/0::int2;
+ERROR:  division by zero
+select 1::numeric/0;
+ERROR:  division by zero
+select 1/0::numeric;
+ERROR:  division by zero
+select 1::float8/0;
+ERROR:  division by zero
+select 1/0::float8;
+ERROR:  division by zero
+select 1::float4/0;
+ERROR:  division by zero
+select 1/0::float4;
+ERROR:  division by zero
index 8efd434a85fbc5598a8179fb2646275b52c8125e..72751ae29e9f090bac20c1615f2292eddcf95eb9 100644 (file)
@@ -113,7 +113,7 @@ SELECT '' AS three, f.f1, f.f1 - '-10' AS x FROM FLOAT4_TBL f
 
 -- test divide by zero
 SELECT '' AS bad, f.f1 / '0.0' from FLOAT4_TBL f;
-ERROR:  float4div: divide by zero error
+ERROR:  division by zero
 SELECT '' AS five, FLOAT4_TBL.*;
  five |      f1      
 ------+--------------
index e03db639c5c408ddee02c96dc2f930bc2663cd33..7ec463b7f311e990eb3602c85c15a6c5f4421004 100644 (file)
@@ -113,7 +113,7 @@ SELECT '' AS three, f.f1, f.f1 - '-10' AS x FROM FLOAT4_TBL f
 
 -- test divide by zero
 SELECT '' AS bad, f.f1 / '0.0' from FLOAT4_TBL f;
-ERROR:  float4div: divide by zero error
+ERROR:  division by zero
 SELECT '' AS five, FLOAT4_TBL.*;
  five |     f1      
 ------+-------------
index b346ed5c38ff49ab6729563deee1a5249c80b752..9d38aee196167fb18db419ab9af774da6d4bfe7e 100644 (file)
@@ -257,7 +257,7 @@ ERROR:  can't take log of a negative number
 SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f;
 ERROR:  exp() result is out of range
 SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f;
-ERROR:  float8div: divide by zero error
+ERROR:  division by zero
 SELECT '' AS five, FLOAT8_TBL.*;
  five |          f1           
 ------+-----------------------
index 15d96ff365da6f45471533c8983cae254347c002..5c2df1e7c016dcb518cbe142321275a3730fc16d 100644 (file)
@@ -257,7 +257,7 @@ ERROR:  can't take log of a negative number
 SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f;
 ERROR:  exp() result is out of range
 SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f;
-ERROR:  float8div: divide by zero error
+ERROR:  division by zero
 SELECT '' AS five, FLOAT8_TBL.*;
  five |          f1           
 ------+-----------------------
index 119051f3993ba1257035e40f80a97933850d9cf8..448bfc40bc21817587462aafeea0de09c12036a2 100644 (file)
@@ -257,7 +257,7 @@ ERROR:  can't take log of a negative number
 SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f;
 ERROR:  exp() result is out of range
 SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f;
-ERROR:  float8div: divide by zero error
+ERROR:  division by zero
 SELECT '' AS five, FLOAT8_TBL.*;
  five |          f1           
 ------+-----------------------
index d91427c6ffa49ac3c50df1117e2315e6ced6cd7a..576768785fd31d671f2ec562b38690d66d2750e5 100644 (file)
@@ -257,7 +257,7 @@ ERROR:  can't take log of a negative number
 SELECT '' AS bad, exp(f.f1) from FLOAT8_TBL f;
 ERROR:  exp() result is out of range
 SELECT '' AS bad, f.f1 / '0.0' from FLOAT8_TBL f;
-ERROR:  float8div: divide by zero error
+ERROR:  division by zero
 SELECT '' AS five, FLOAT8_TBL.*;
  five |          f1           
 ------+-----------------------
index dee19bc136f4f42a0283c0fe7872709352fc690d..5876244ee3bd55e63e73cdb4744ff8d9fa963512 100644 (file)
@@ -17,7 +17,7 @@ select 1;
 --
 
 --
--- RETRIEVE
+-- SELECT
  
 -- missing relation name 
 select;
@@ -55,7 +55,7 @@ delete from nonesuch;
 
 
 --
--- DESTROY
+-- DROP
  
 -- missing relation name (this had better not wildcard!) 
 drop table;
@@ -65,9 +65,8 @@ drop table nonesuch;
 
 
 --
--- RENAME
+-- ALTER TABLE
  
-
 -- relation renaming 
 
 -- missing relation name 
@@ -112,7 +111,7 @@ end;
 
 
 --
--- DEFINE AGGREGATE
+-- CREATE AGGREGATE
 
 -- sfunc/finalfunc type disagreement 
 create aggregate newavg2 (sfunc = int4pl,
@@ -128,7 +127,7 @@ create aggregate newcnt1 (sfunc = int4inc,
 
 
 --
--- REMOVE INDEX
+-- DROP INDEX
  
 -- missing index name 
 drop index;
@@ -141,7 +140,7 @@ drop index nonesuch;
 
 
 --
--- REMOVE AGGREGATE
+-- DROP AGGREGATE
  
 -- missing aggregate name 
 drop aggregate;
@@ -163,7 +162,7 @@ drop aggregate newcnt (float4);
 
 
 --
--- REMOVE FUNCTION
+-- DROP FUNCTION
  
 -- missing function name 
 drop function ();
@@ -176,7 +175,7 @@ drop function nonesuch();
 
 
 --
--- REMOVE TYPE
+-- DROP TYPE
  
 -- missing type name 
 drop type;
@@ -252,3 +251,28 @@ drop instance rule nonesuch on noplace;
 -- no such rule 
 drop rewrite rule nonesuch;
 
+--
+-- Check that division-by-zero is properly caught.
+--
+
+select 1/0;
+
+select 1::int8/0;
+
+select 1/0::int8;
+
+select 1::int2/0;
+
+select 1/0::int2;
+
+select 1::numeric/0;
+
+select 1/0::numeric;
+
+select 1::float8/0;
+
+select 1/0::float8;
+
+select 1::float4/0;
+
+select 1/0::float4;