diff options
-rw-r--r-- | src/backend/utils/adt/numeric.c | 21 | ||||
-rw-r--r-- | src/test/regress/expected/numeric.out | 31 | ||||
-rw-r--r-- | src/test/regress/sql/numeric.sql | 7 |
3 files changed, 57 insertions, 2 deletions
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index dcf31e340c1..8dfdffcfbd1 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -2972,10 +2972,27 @@ numeric_power(PG_FUNCTION_ARGS) NumericVar result; /* - * Handle NaN + * Handle NaN cases. We follow the POSIX spec for pow(3), which says that + * NaN ^ 0 = 1, and 1 ^ NaN = 1, while all other cases with NaN inputs + * yield NaN (with no error). */ - if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2)) + if (NUMERIC_IS_NAN(num1)) + { + if (!NUMERIC_IS_NAN(num2)) + { + init_var_from_num(num2, &arg2); + if (cmp_var(&arg2, &const_zero) == 0) + PG_RETURN_NUMERIC(make_result(&const_one)); + } PG_RETURN_NUMERIC(make_result(&const_nan)); + } + if (NUMERIC_IS_NAN(num2)) + { + init_var_from_num(num1, &arg1); + if (cmp_var(&arg1, &const_one) == 0) + PG_RETURN_NUMERIC(make_result(&const_one)); + PG_RETURN_NUMERIC(make_result(&const_nan)); + } /* * Initialize things diff --git a/src/test/regress/expected/numeric.out b/src/test/regress/expected/numeric.out index 17985e85401..1cb3c3bfab7 100644 --- a/src/test/regress/expected/numeric.out +++ b/src/test/regress/expected/numeric.out @@ -1664,6 +1664,37 @@ select 0.0 ^ 12.34; 0.0000000000000000 (1 row) +-- NaNs +select 'NaN'::numeric ^ 'NaN'::numeric; + ?column? +---------- + NaN +(1 row) + +select 'NaN'::numeric ^ 0; + ?column? +---------- + 1 +(1 row) + +select 'NaN'::numeric ^ 1; + ?column? +---------- + NaN +(1 row) + +select 0 ^ 'NaN'::numeric; + ?column? +---------- + NaN +(1 row) + +select 1 ^ 'NaN'::numeric; + ?column? +---------- + 1 +(1 row) + -- invalid inputs select 0.0 ^ (-12.34); ERROR: zero raised to a negative power is undefined diff --git a/src/test/regress/sql/numeric.sql b/src/test/regress/sql/numeric.sql index d77504e6246..a9394123596 100644 --- a/src/test/regress/sql/numeric.sql +++ b/src/test/regress/sql/numeric.sql @@ -911,6 +911,13 @@ select (-12.34) ^ 0.0; select 12.34 ^ 0.0; select 0.0 ^ 12.34; +-- NaNs +select 'NaN'::numeric ^ 'NaN'::numeric; +select 'NaN'::numeric ^ 0; +select 'NaN'::numeric ^ 1; +select 0 ^ 'NaN'::numeric; +select 1 ^ 'NaN'::numeric; + -- invalid inputs select 0.0 ^ (-12.34); select (-12.34) ^ 1.2; |