From 8a4dc94ca0efec20b656f61f2efd3ab7f0d64ae7 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Fri, 30 Jul 2010 04:30:23 +0000
Subject: [PATCH] Make details of the Numeric representation private to
 numeric.c.

Review by Tom Lane.
---
 contrib/btree_gist/btree_numeric.c  |  6 +--
 src/backend/utils/adt/format_type.c | 12 +-----
 src/backend/utils/adt/numeric.c     | 65 ++++++++++++++++++++++++++++-
 src/include/utils/numeric.h         | 42 +++----------------
 4 files changed, 75 insertions(+), 50 deletions(-)

diff --git a/contrib/btree_gist/btree_numeric.c b/contrib/btree_gist/btree_numeric.c
index 810bb279da..6331109b10 100644
--- a/contrib/btree_gist/btree_numeric.c
+++ b/contrib/btree_gist/btree_numeric.c
@@ -1,5 +1,5 @@
 /*
- * $PostgreSQL: pgsql/contrib/btree_gist/btree_numeric.c,v 1.13 2009/06/11 14:48:50 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/btree_gist/btree_numeric.c,v 1.14 2010/07/30 04:30:23 rhaas Exp $
  */
 #include "btree_gist.h"
 
@@ -185,9 +185,9 @@ gbt_numeric_penalty(PG_FUNCTION_ARGS)
 											 NumericGetDatum(os)
 											 ));
 
-	if (NUMERIC_IS_NAN(us))
+	if (numeric_is_nan(us))
 	{
-		if (NUMERIC_IS_NAN(os))
+		if (numeric_is_nan(os))
 			*result = 0.0;
 		else
 			*result = 1.0;
diff --git a/src/backend/utils/adt/format_type.c b/src/backend/utils/adt/format_type.c
index bdb1d62814..2de07693af 100644
--- a/src/backend/utils/adt/format_type.c
+++ b/src/backend/utils/adt/format_type.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.53 2010/02/14 18:42:16 rhaas Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/format_type.c,v 1.54 2010/07/30 04:30:23 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -387,15 +387,7 @@ type_maximum_size(Oid type_oid, int32 typemod)
 				+ VARHDRSZ;
 
 		case NUMERICOID:
-			/* precision (ie, max # of digits) is in upper bits of typmod */
-			if (typemod > VARHDRSZ)
-			{
-				int			precision = ((typemod - VARHDRSZ) >> 16) & 0xffff;
-
-				/* Numeric stores 2 decimal digits/byte, plus header */
-				return (precision + 1) / 2 + NUMERIC_HDRSZ;
-			}
-			break;
+			return numeric_maximum_size(typemod);
 
 		case VARBITOID:
 		case BITOID:
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index 4b8271e45f..327d5f0ddf 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
  * Copyright (c) 1998-2010, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.123 2010/02/26 02:01:09 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/numeric.c,v 1.124 2010/07/30 04:30:23 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,6 +35,38 @@
 #include "utils/int8.h"
 #include "utils/numeric.h"
 
+/*
+ * Sign values and macros to deal with packing/unpacking n_sign_dscale
+ */
+#define NUMERIC_SIGN_MASK	0xC000
+#define NUMERIC_POS			0x0000
+#define NUMERIC_NEG			0x4000
+#define NUMERIC_NAN			0xC000
+#define NUMERIC_DSCALE_MASK 0x3FFF
+#define NUMERIC_SIGN(n)		((n)->n_sign_dscale & NUMERIC_SIGN_MASK)
+#define NUMERIC_DSCALE(n)	((n)->n_sign_dscale & NUMERIC_DSCALE_MASK)
+#define NUMERIC_IS_NAN(n)	(NUMERIC_SIGN(n) != NUMERIC_POS &&	\
+							 NUMERIC_SIGN(n) != NUMERIC_NEG)
+#define NUMERIC_HDRSZ	(VARHDRSZ + sizeof(uint16) + sizeof(int16))
+
+
+/*
+ * The Numeric data type stored in the database
+ *
+ * NOTE: by convention, values in the packed form have been stripped of
+ * all leading and trailing zero digits (where a "digit" is of base NBASE).
+ * In particular, if the value is zero, there will be no digits at all!
+ * The weight is arbitrary in that case, but we normally set it to zero.
+ */
+struct NumericData
+{
+	int32		vl_len_;		/* varlena header (do not touch directly!) */
+	uint16		n_sign_dscale;	/* Sign + display scale */
+	int16		n_weight;		/* Weight of 1st digit	*/
+	char		n_data[1];		/* Digits (really array of NumericDigit) */
+};
+
+
 /* ----------
  * Uncomment the following to enable compilation of dump_numeric()
  * and dump_var() and to get a dump of any result produced by make_result().
@@ -427,6 +459,37 @@ numeric_out(PG_FUNCTION_ARGS)
 	PG_RETURN_CSTRING(str);
 }
 
+/*
+ * numeric_is_nan() -
+ *
+ *  Is Numeric value a NaN?
+ */
+bool
+numeric_is_nan(Numeric num)
+{
+	return NUMERIC_IS_NAN(num);
+}
+
+/*
+ * numeric_maximum_size() -
+ *
+ *  Maximum size of a numeric with given typmod, or -1 if unlimited/unknown.
+ */
+int32
+numeric_maximum_size(int32 typemod)
+{
+	int precision;
+
+	if (typemod <= VARHDRSZ)
+		return -1;
+
+	/* precision (ie, max # of digits) is in upper bits of typmod */
+	precision = ((typemod - VARHDRSZ) >> 16) & 0xffff;
+
+	/* Numeric stores 2 decimal digits/byte, plus header */
+	return (precision + 1) / 2 + NUMERIC_HDRSZ;
+}
+
 /*
  * numeric_out_sci() -
  *
diff --git a/src/include/utils/numeric.h b/src/include/utils/numeric.h
index 6096439e5b..7bbe34bdea 100644
--- a/src/include/utils/numeric.h
+++ b/src/include/utils/numeric.h
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1998-2010, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/utils/numeric.h,v 1.29 2010/01/02 16:58:10 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/utils/numeric.h,v 1.30 2010/07/30 04:30:23 rhaas Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,41 +37,9 @@
  */
 #define NUMERIC_MIN_SIG_DIGITS		16
 
-
-/*
- * Sign values and macros to deal with packing/unpacking n_sign_dscale
- */
-#define NUMERIC_SIGN_MASK	0xC000
-#define NUMERIC_POS			0x0000
-#define NUMERIC_NEG			0x4000
-#define NUMERIC_NAN			0xC000
-#define NUMERIC_DSCALE_MASK 0x3FFF
-#define NUMERIC_SIGN(n)		((n)->n_sign_dscale & NUMERIC_SIGN_MASK)
-#define NUMERIC_DSCALE(n)	((n)->n_sign_dscale & NUMERIC_DSCALE_MASK)
-#define NUMERIC_IS_NAN(n)	(NUMERIC_SIGN(n) != NUMERIC_POS &&	\
-							 NUMERIC_SIGN(n) != NUMERIC_NEG)
-
-
-/*
- * The Numeric data type stored in the database
- *
- * NOTE: by convention, values in the packed form have been stripped of
- * all leading and trailing zero digits (where a "digit" is of base NBASE).
- * In particular, if the value is zero, there will be no digits at all!
- * The weight is arbitrary in that case, but we normally set it to zero.
- */
-typedef struct NumericData
-{
-	int32		vl_len_;		/* varlena header (do not touch directly!) */
-	uint16		n_sign_dscale;	/* Sign + display scale */
-	int16		n_weight;		/* Weight of 1st digit	*/
-	char		n_data[1];		/* Digits (really array of NumericDigit) */
-} NumericData;
-
-typedef NumericData *Numeric;
-
-#define NUMERIC_HDRSZ	(VARHDRSZ + sizeof(uint16) + sizeof(int16))
-
+/* The actual contents of Numeric are private to numeric.c */
+struct NumericData;
+typedef struct NumericData *Numeric;
 
 /*
  * fmgr interface macros
@@ -87,6 +55,8 @@ typedef NumericData *Numeric;
 /*
  * Utility functions in numeric.c
  */
+extern bool numeric_is_nan(Numeric num);
+int32 numeric_maximum_size(int32 typemod);
 extern char *numeric_out_sci(Numeric num, int scale);
 
 #endif   /* _PG_NUMERIC_H_ */
-- 
2.49.0