From 4a586bd405c2c4905a0a6964275ecfdc324f0e8e Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Thu, 8 May 2008 22:17:54 +0000
Subject: [PATCH] Add regression test for various power expressions with a zero
 base, and adjust source code to be more modular.

---
 src/backend/utils/adt/numeric.c      | 33 ++++++++++++++--------------
 src/test/regress/expected/float8.out |  6 +++++
 src/test/regress/sql/float8.sql      |  2 ++
 3 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index defdc623cd..a8cd22611d 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
  * Copyright (c) 1998-2008, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.111 2008/05/08 19:25:38 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.112 2008/05/08 22:17:54 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -5170,21 +5170,6 @@ power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
 	int			local_rscale;
 	double		val;
 
-	/*
-	 *	This avoids log(0) for cases of 0 raised to a non-integer.
-	 *	Also, while 0 ^ 0 can be either 1 or indeterminate (error), we
-	 *	treat it as one because most programming languages do this.
-	 *	http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
-	 */
-	if (cmp_var(base, &const_zero) == 0)
-	{
-		if (cmp_var(exp, &const_zero) == 0)
-			set_var_from_var(&const_one, result);
-		else
-			set_var_from_var(&const_zero, result);
-		return;
-	}
-	
 	/* If exp can be represented as an integer, use power_var_int */
 	if (exp->ndigits == 0 || exp->ndigits <= exp->weight + 1)
 	{
@@ -5217,6 +5202,17 @@ power_var(NumericVar *base, NumericVar *exp, NumericVar *result)
 		free_var(&x);
 	}
 
+	/*
+	 *	This avoids log(0) for cases of 0 raised to a non-integer.
+	 *	0 ^ 0 handled by power_var_int().
+	 */
+	if (cmp_var(base, &const_zero) == 0)
+	{
+		set_var_from_var(&const_zero, result);
+		result->dscale = NUMERIC_MIN_SIG_DIGITS;	/* no need to round */
+		return;
+	}
+	
 	init_var(&ln_base);
 	init_var(&ln_num);
 
@@ -5284,6 +5280,11 @@ power_var_int(NumericVar *base, int exp, NumericVar *result, int rscale)
 	switch (exp)
 	{
 		case 0:
+			/*
+			 *	While 0 ^ 0 can be either 1 or indeterminate (error), we
+			 *	treat it as 1 because most programming languages do this.
+			 *	http://en.wikipedia.org/wiki/Exponentiation#Zero_to_the_zero_power
+			 */
 			set_var_from_var(&const_one, result);
 			result->dscale = rscale;	/* no need to round */
 			return;
diff --git a/src/test/regress/expected/float8.out b/src/test/regress/expected/float8.out
index 38d2cbfb41..f81d9b2bac 100644
--- a/src/test/regress/expected/float8.out
+++ b/src/test/regress/expected/float8.out
@@ -349,6 +349,12 @@ SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f;
 ERROR:  value out of range: overflow
 SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
 ERROR:  value out of range: overflow
+SELECT 0 ^ 0 + 0 ^ 1 + 0 ^ 0.0 + 0 ^ 0.5;
+ ?column? 
+----------
+        2
+(1 row)
+
 SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ;
 ERROR:  cannot take logarithm of zero
 SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;
diff --git a/src/test/regress/sql/float8.sql b/src/test/regress/sql/float8.sql
index b4dd7be4b3..92b6b0d7b9 100644
--- a/src/test/regress/sql/float8.sql
+++ b/src/test/regress/sql/float8.sql
@@ -129,6 +129,8 @@ SELECT '' AS bad, f.f1 * '1e200' from FLOAT8_TBL f;
 
 SELECT '' AS bad, f.f1 ^ '1e200' from FLOAT8_TBL f;
 
+SELECT 0 ^ 0 + 0 ^ 1 + 0 ^ 0.0 + 0 ^ 0.5;
+
 SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 = '0.0' ;
 
 SELECT '' AS bad, ln(f.f1) from FLOAT8_TBL f where f.f1 < '0.0' ;
-- 
2.40.0