Commit 2871f60f authored by Neil Conway's avatar Neil Conway

Change ln(), log(), power(), and sqrt() to emit the correct SQLSTATE

error codes for certain error conditions, as specified by SQL2003.
parent 335cf9ae
<!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.5 2004/05/14 21:42:27 neilc Exp $ --> <!-- $PostgreSQL: pgsql/doc/src/sgml/errcodes.sgml,v 1.6 2004/05/16 23:18:52 neilc Exp $ -->
<appendix id="errcodes-appendix"> <appendix id="errcodes-appendix">
<title><productname>PostgreSQL</productname> Error Codes</title> <title><productname>PostgreSQL</productname> Error Codes</title>
...@@ -310,6 +310,16 @@ ...@@ -310,6 +310,16 @@
<entry>INTERVAL FIELD OVERFLOW</entry> <entry>INTERVAL FIELD OVERFLOW</entry>
</row> </row>
<row>
<entry><literal>2201E</literal></entry>
<entry>INVALID ARGUMENT FOR LOGARITHM</entry>
</row>
<row>
<entry><literal>2201F</literal></entry>
<entry>INVALID ARGUMENT FOR POWER FUNCTION</entry>
</row>
<row> <row>
<entry><literal>2201G</literal></entry> <entry><literal>2201G</literal></entry>
<entry>INVALID ARGUMENT FOR WIDTH BUCKET FUNCTION</entry> <entry>INVALID ARGUMENT FOR WIDTH BUCKET FUNCTION</entry>
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.104 2004/05/07 00:24:58 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.105 2004/05/16 23:18:55 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1415,7 +1415,7 @@ dsqrt(PG_FUNCTION_ARGS) ...@@ -1415,7 +1415,7 @@ dsqrt(PG_FUNCTION_ARGS)
if (arg1 < 0) if (arg1 < 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FLOATING_POINT_EXCEPTION), (errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
errmsg("cannot take square root of a negative number"))); errmsg("cannot take square root of a negative number")));
result = sqrt(arg1); result = sqrt(arg1);
...@@ -1449,6 +1449,16 @@ dpow(PG_FUNCTION_ARGS) ...@@ -1449,6 +1449,16 @@ dpow(PG_FUNCTION_ARGS)
float8 arg2 = PG_GETARG_FLOAT8(1); float8 arg2 = PG_GETARG_FLOAT8(1);
float8 result; float8 result;
/*
* The SQL spec requires that we emit a particular SQLSTATE error
* code for certain error conditions.
*/
if ((arg1 == 0 && arg2 < 0) ||
(arg1 < 0 && floor(arg2) != arg2))
ereport(ERROR,
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
errmsg("invalid argument for power function")));
/* /*
* We must check both for errno getting set and for a NaN result, in * We must check both for errno getting set and for a NaN result, in
* order to deal with the vagaries of different platforms... * order to deal with the vagaries of different platforms...
...@@ -1501,7 +1511,6 @@ dexp(PG_FUNCTION_ARGS) ...@@ -1501,7 +1511,6 @@ dexp(PG_FUNCTION_ARGS)
/* /*
* dlog1 - returns the natural logarithm of arg1 * dlog1 - returns the natural logarithm of arg1
* ("dlog" is already a logging routine...)
*/ */
Datum Datum
dlog1(PG_FUNCTION_ARGS) dlog1(PG_FUNCTION_ARGS)
...@@ -1509,14 +1518,17 @@ dlog1(PG_FUNCTION_ARGS) ...@@ -1509,14 +1518,17 @@ dlog1(PG_FUNCTION_ARGS)
float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg1 = PG_GETARG_FLOAT8(0);
float8 result; float8 result;
/*
* Emit particular SQLSTATE error codes for ln(). This is required
* by the SQL standard.
*/
if (arg1 == 0.0) if (arg1 == 0.0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FLOATING_POINT_EXCEPTION), (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
errmsg("cannot take logarithm of zero"))); errmsg("cannot take logarithm of zero")));
if (arg1 < 0) if (arg1 < 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FLOATING_POINT_EXCEPTION), (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
errmsg("cannot take logarithm of a negative number"))); errmsg("cannot take logarithm of a negative number")));
result = log(arg1); result = log(arg1);
...@@ -1535,14 +1547,19 @@ dlog10(PG_FUNCTION_ARGS) ...@@ -1535,14 +1547,19 @@ dlog10(PG_FUNCTION_ARGS)
float8 arg1 = PG_GETARG_FLOAT8(0); float8 arg1 = PG_GETARG_FLOAT8(0);
float8 result; float8 result;
/*
* Emit particular SQLSTATE error codes for log(). The SQL spec
* doesn't define log(), but it does define ln(), so it makes
* sense to emit the same error code for an analogous error
* condition.
*/
if (arg1 == 0.0) if (arg1 == 0.0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FLOATING_POINT_EXCEPTION), (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
errmsg("cannot take logarithm of zero"))); errmsg("cannot take logarithm of zero")));
if (arg1 < 0) if (arg1 < 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FLOATING_POINT_EXCEPTION), (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
errmsg("cannot take logarithm of a negative number"))); errmsg("cannot take logarithm of a negative number")));
result = log10(arg1); result = log10(arg1);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* Copyright (c) 1998-2003, PostgreSQL Global Development Group * Copyright (c) 1998-2003, PostgreSQL Global Development Group
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.74 2004/05/14 21:42:28 neilc Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.75 2004/05/16 23:18:55 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1668,6 +1668,7 @@ numeric_power(PG_FUNCTION_ARGS) ...@@ -1668,6 +1668,7 @@ numeric_power(PG_FUNCTION_ARGS)
Numeric res; Numeric res;
NumericVar arg1; NumericVar arg1;
NumericVar arg2; NumericVar arg2;
NumericVar arg2_trunc;
NumericVar result; NumericVar result;
/* /*
...@@ -1681,10 +1682,26 @@ numeric_power(PG_FUNCTION_ARGS) ...@@ -1681,10 +1682,26 @@ numeric_power(PG_FUNCTION_ARGS)
*/ */
init_var(&arg1); init_var(&arg1);
init_var(&arg2); init_var(&arg2);
init_var(&arg2_trunc);
init_var(&result); init_var(&result);
set_var_from_num(num1, &arg1); set_var_from_num(num1, &arg1);
set_var_from_num(num2, &arg2); set_var_from_num(num2, &arg2);
set_var_from_var(&arg2, &arg2_trunc);
trunc_var(&arg2_trunc, 0);
/*
* Return special SQLSTATE error codes for a few conditions
* mandated by the standard.
*/
if ((cmp_var(&arg1, &const_zero) == 0 &&
cmp_var(&arg2, &const_zero) < 0) ||
(cmp_var(&arg1, &const_zero) < 0 &&
cmp_var(&arg2, &arg2_trunc) != 0))
ereport(ERROR,
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION),
errmsg("invalid argument for power function")));
/* /*
* Call power_var() to compute and return the result; note it handles * Call power_var() to compute and return the result; note it handles
...@@ -1696,6 +1713,7 @@ numeric_power(PG_FUNCTION_ARGS) ...@@ -1696,6 +1713,7 @@ numeric_power(PG_FUNCTION_ARGS)
free_var(&result); free_var(&result);
free_var(&arg2); free_var(&arg2);
free_var(&arg2_trunc);
free_var(&arg1); free_var(&arg1);
PG_RETURN_NUMERIC(res); PG_RETURN_NUMERIC(res);
...@@ -4408,10 +4426,16 @@ ln_var(NumericVar *arg, NumericVar *result, int rscale) ...@@ -4408,10 +4426,16 @@ ln_var(NumericVar *arg, NumericVar *result, int rscale)
NumericVar elem; NumericVar elem;
NumericVar fact; NumericVar fact;
int local_rscale; int local_rscale;
int cmp;
if (cmp_var(arg, &const_zero) <= 0) cmp = cmp_var(arg, &const_zero);
if (cmp == 0)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FLOATING_POINT_EXCEPTION), (errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
errmsg("cannot take logarithm of zero")));
else if (cmp < 0)
ereport(ERROR,
(errcode(ERRCODE_INVALID_ARGUMENT_FOR_LOG),
errmsg("cannot take logarithm of a negative number"))); errmsg("cannot take logarithm of a negative number")));
local_rscale = rscale + 8; local_rscale = rscale + 8;
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* Copyright (c) 2003, PostgreSQL Global Development Group * Copyright (c) 2003, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.10 2004/05/14 21:42:30 neilc Exp $ * $PostgreSQL: pgsql/src/include/utils/errcodes.h,v 1.11 2004/05/16 23:18:55 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -116,7 +116,9 @@ ...@@ -116,7 +116,9 @@
#define ERRCODE_ESCAPE_CHARACTER_CONFLICT MAKE_SQLSTATE('2','2', '0','0','B') #define ERRCODE_ESCAPE_CHARACTER_CONFLICT MAKE_SQLSTATE('2','2', '0','0','B')
#define ERRCODE_INDICATOR_OVERFLOW MAKE_SQLSTATE('2','2', '0','2','2') #define ERRCODE_INDICATOR_OVERFLOW MAKE_SQLSTATE('2','2', '0','2','2')
#define ERRCODE_INTERVAL_FIELD_OVERFLOW MAKE_SQLSTATE('2','2', '0','1','5') #define ERRCODE_INTERVAL_FIELD_OVERFLOW MAKE_SQLSTATE('2','2', '0','1','5')
#define ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION MAKE_SQLSTATE('2','2', '0', '1', 'G') #define ERRCODE_INVALID_ARGUMENT_FOR_LOG MAKE_SQLSTATE('2','2', '0','1','E')
#define ERRCODE_INVALID_ARGUMENT_FOR_POWER_FUNCTION MAKE_SQLSTATE('2','2', '0', '1', 'F')
#define ERRCODE_INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION MAKE_SQLSTATE('2','2', '0', '1', 'G')
#define ERRCODE_INVALID_CHARACTER_VALUE_FOR_CAST MAKE_SQLSTATE('2','2', '0','1','8') #define ERRCODE_INVALID_CHARACTER_VALUE_FOR_CAST MAKE_SQLSTATE('2','2', '0','1','8')
#define ERRCODE_INVALID_DATETIME_FORMAT MAKE_SQLSTATE('2','2', '0','0','7') #define ERRCODE_INVALID_DATETIME_FORMAT MAKE_SQLSTATE('2','2', '0','0','7')
#define ERRCODE_INVALID_ESCAPE_CHARACTER MAKE_SQLSTATE('2','2', '0','1','9') #define ERRCODE_INVALID_ESCAPE_CHARACTER MAKE_SQLSTATE('2','2', '0','1','9')
......
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