Hi,
Here's a patch for the second function suggested in
5643125e.1030...@joh.to. This is my first patch trying to do anything
with numerics, so please be gentle. I'm sure it's full of stupid.
January's commit fest, feedback welcome, yada yada..
.m
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
***************
*** 782,787 ****
--- 782,800 ----
<row>
<entry>
<indexterm>
+ <primary>numeric_trim</primary>
+ </indexterm>
+
<literal><function>numeric_trim(<type>numeric</type>)</function></literal>
+ </entry>
+ <entry><type>numeric</type></entry>
+ <entry>remove trailing decimal zeroes after the decimal point</entry>
+ <entry><literal>numeric_trim(8.4100)</literal></entry>
+ <entry><literal>8.41</literal></entry>
+ </row>
+
+ <row>
+ <entry>
+ <indexterm>
<primary>pi</primary>
</indexterm>
<literal><function>pi()</function></literal>
*** a/src/backend/utils/adt/numeric.c
--- b/src/backend/utils/adt/numeric.c
***************
*** 2825,2830 **** numeric_power(PG_FUNCTION_ARGS)
--- 2825,2904 ----
PG_RETURN_NUMERIC(res);
}
+ /*
+ * numeric_trim() -
+ *
+ * Remove trailing decimal zeroes after the decimal point
+ */
+ Datum
+ numeric_trim(PG_FUNCTION_ARGS)
+ {
+ Numeric num = PG_GETARG_NUMERIC(0);
+ NumericVar arg;
+ Numeric res;
+ int dscale;
+ int ndigits;
+
+ if (NUMERIC_IS_NAN(num))
+ PG_RETURN_NUMERIC(make_result(&const_nan));
+
+ init_var_from_num(num, &arg);
+
+ ndigits = arg.ndigits;
+ /* for simplicity in the loop below, do full NBASE digits at a time */
+ dscale = ((arg.dscale + DEC_DIGITS - 1) / DEC_DIGITS) * DEC_DIGITS;
+ /* trim unstored significant trailing zeroes right away */
+ if (dscale > (ndigits - arg.weight - 1) * DEC_DIGITS)
+ dscale = (ndigits - arg.weight - 1) * DEC_DIGITS;
+ while (dscale > 0 && ndigits > 0)
+ {
+ NumericDigit dig = arg.digits[ndigits - 1];
+
+ #if DEC_DIGITS == 4
+ if ((dig % 10) != 0)
+ break;
+ if (--dscale == 0)
+ break;
+ if ((dig % 100) != 0)
+ break;
+ if (--dscale == 0)
+ break;
+ if ((dig % 1000) != 0)
+ break;
+ if (--dscale == 0)
+ break;
+ #elif DEC_DIGITS == 2
+ if ((dig % 10) != 0)
+ break;
+ if (--dscale == 0)
+ break;
+ #elif DEC_DIGITS == 1
+ /* nothing to do */
+ #else
+ #error unsupported NBASE
+ #endif
+ if (dig != 0)
+ break;
+ --dscale;
+ --ndigits;
+ }
+ arg.dscale = dscale;
+ arg.ndigits = ndigits;
+
+ /* If it's zero, normalize the sign and weight */
+ if (ndigits == 0)
+ {
+ arg.sign = NUMERIC_POS;
+ arg.weight = 0;
+ arg.dscale = 0;
+ }
+
+ res = make_result(&arg);
+ free_var(&arg);
+
+ PG_RETURN_NUMERIC(res);
+ }
+
/* ----------------------------------------------------------------------
*
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
***************
*** 2361,2366 **** DESCR("exponentiation");
--- 2361,2368 ----
DATA(insert OID = 2169 ( power PGNSP
PGUID 12 1 0 0 0 f f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_
_null_ _null_ numeric_power _null_ _null_ _null_ ));
DESCR("exponentiation");
DATA(insert OID = 1739 ( numeric_power PGNSP PGUID 12
1 0 0 0 f f f f t f i s 2 0 1700 "1700 1700" _null_ _null_ _null_ _null_ _null_
numeric_power _null_ _null_ _null_ ));
+ DATA(insert OID = 8888 ( numeric_trim PGNSP PGUID 12 1 0 0 0
f f f f t f i s 1 0 1700 "1700" _null_ _null_ _null_ _null_ _null_
numeric_trim _null_ _null_ _null_ ));
+ DESCR("remove trailing decimal zeroes after the decimal point");
DATA(insert OID = 1740 ( numeric PGNSP PGUID 12
1 0 0 0 f f f f t f i s 1 0 1700 "23" _null_ _null_ _null_ _null_ _null_
int4_numeric _null_ _null_ _null_ ));
DESCR("convert int4 to numeric");
DATA(insert OID = 1741 ( log PGNSP PGUID 14
1 0 0 0 f f f f t f i s 1 0 1700 "1700" _null_ _null_ _null_ _null_ _null_
"select pg_catalog.log(10, $1)" _null_ _null_ _null_ ));
*** a/src/include/utils/builtins.h
--- b/src/include/utils/builtins.h
***************
*** 1022,1027 **** extern Datum numeric_exp(PG_FUNCTION_ARGS);
--- 1022,1028 ----
extern Datum numeric_ln(PG_FUNCTION_ARGS);
extern Datum numeric_log(PG_FUNCTION_ARGS);
extern Datum numeric_power(PG_FUNCTION_ARGS);
+ extern Datum numeric_trim(PG_FUNCTION_ARGS);
extern Datum int4_numeric(PG_FUNCTION_ARGS);
extern Datum numeric_int4(PG_FUNCTION_ARGS);
extern Datum int8_numeric(PG_FUNCTION_ARGS);
*** a/src/test/regress/expected/numeric.out
--- b/src/test/regress/expected/numeric.out
***************
*** 1852,1854 **** select log(3.1954752e47, 9.4792021e-73);
--- 1852,2013 ----
-1.51613372350688302142917386143459361608600157692779164475351842333265418126982165
(1 row)
+ --
+ -- Tests for numeric_trim()
+ --
+ select numeric_trim('NaN');
+ numeric_trim
+ --------------
+ NaN
+ (1 row)
+
+ select numeric_trim('0');
+ numeric_trim
+ --------------
+ 0
+ (1 row)
+
+ select numeric_trim('0.0');
+ numeric_trim
+ --------------
+ 0
+ (1 row)
+
+ select numeric_trim('0.0000000000000000000000');
+ numeric_trim
+ --------------
+ 0
+ (1 row)
+
+ select numeric_trim('1.0');
+ numeric_trim
+ --------------
+ 1
+ (1 row)
+
+ select numeric_trim('1.00');
+ numeric_trim
+ --------------
+ 1
+ (1 row)
+
+ select numeric_trim('1.00000');
+ numeric_trim
+ --------------
+ 1
+ (1 row)
+
+ select numeric_trim('1.1');
+ numeric_trim
+ --------------
+ 1.1
+ (1 row)
+
+ select numeric_trim('1.11');
+ numeric_trim
+ --------------
+ 1.11
+ (1 row)
+
+ select numeric_trim('1.111');
+ numeric_trim
+ --------------
+ 1.111
+ (1 row)
+
+ select numeric_trim('1.1111');
+ numeric_trim
+ --------------
+ 1.1111
+ (1 row)
+
+ select numeric_trim('1.11111');
+ numeric_trim
+ --------------
+ 1.11111
+ (1 row)
+
+ select numeric_trim('1.010');
+ numeric_trim
+ --------------
+ 1.01
+ (1 row)
+
+ select numeric_trim('1.0010');
+ numeric_trim
+ --------------
+ 1.001
+ (1 row)
+
+ select numeric_trim('1.00010');
+ numeric_trim
+ --------------
+ 1.0001
+ (1 row)
+
+ select numeric_trim('1.000010');
+ numeric_trim
+ --------------
+ 1.00001
+ (1 row)
+
+ select numeric_trim('1.00001000000');
+ numeric_trim
+ --------------
+ 1.00001
+ (1 row)
+
+ select numeric_trim('1.001000000');
+ numeric_trim
+ --------------
+ 1.001
+ (1 row)
+
+ select numeric_trim('5124124800.10');
+ numeric_trim
+ --------------
+ 5124124800.1
+ (1 row)
+
+ select numeric_trim('5124124800.010');
+ numeric_trim
+ ---------------
+ 5124124800.01
+ (1 row)
+
+ select numeric_trim('5124124800.0010');
+ numeric_trim
+ ----------------
+ 5124124800.001
+ (1 row)
+
+ select numeric_trim('5124124800.00010');
+ numeric_trim
+ -----------------
+ 5124124800.0001
+ (1 row)
+
+ select numeric_trim('5124124800.000010');
+ numeric_trim
+ ------------------
+ 5124124800.00001
+ (1 row)
+
+ select numeric_trim('5124124800.0000010');
+ numeric_trim
+ -------------------
+ 5124124800.000001
+ (1 row)
+
+ select numeric_trim('5124124800.00000100000000000');
+ numeric_trim
+ -------------------
+ 5124124800.000001
+ (1 row)
+
+ select numeric_trim('5124124800.00100000000000');
+ numeric_trim
+ ----------------
+ 5124124800.001
+ (1 row)
+
*** a/src/test/regress/sql/numeric.sql
--- b/src/test/regress/sql/numeric.sql
***************
*** 983,985 **** select log(1.23e-89, 6.4689e45);
--- 983,1017 ----
select log(0.99923, 4.58934e34);
select log(1.000016, 8.452010e18);
select log(3.1954752e47, 9.4792021e-73);
+
+
+ --
+ -- Tests for numeric_trim()
+ --
+
+ select numeric_trim('NaN');
+ select numeric_trim('0');
+ select numeric_trim('0.0');
+ select numeric_trim('0.0000000000000000000000');
+ select numeric_trim('1.0');
+ select numeric_trim('1.00');
+ select numeric_trim('1.00000');
+ select numeric_trim('1.1');
+ select numeric_trim('1.11');
+ select numeric_trim('1.111');
+ select numeric_trim('1.1111');
+ select numeric_trim('1.11111');
+ select numeric_trim('1.010');
+ select numeric_trim('1.0010');
+ select numeric_trim('1.00010');
+ select numeric_trim('1.000010');
+ select numeric_trim('1.00001000000');
+ select numeric_trim('1.001000000');
+ select numeric_trim('5124124800.10');
+ select numeric_trim('5124124800.010');
+ select numeric_trim('5124124800.0010');
+ select numeric_trim('5124124800.00010');
+ select numeric_trim('5124124800.000010');
+ select numeric_trim('5124124800.0000010');
+ select numeric_trim('5124124800.00000100000000000');
+ select numeric_trim('5124124800.00100000000000');
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers