From 8a4dc94ca0efec20b656f61f2efd3ab7f0d64ae7 Mon Sep 17 00:00:00 2001 From: Robert Haas 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_ */