|
13 | 13 | * this version handles 64 bit numbers and so can hold values up to
|
14 | 14 | * $92,233,720,368,547,758.07.
|
15 | 15 | *
|
16 |
| - * $PostgreSQL: pgsql/src/backend/utils/adt/cash.c,v 1.82 2009/06/11 14:49:03 momjian Exp $ |
| 16 | + * $PostgreSQL: pgsql/src/backend/utils/adt/cash.c,v 1.83 2010/07/16 02:15:53 tgl Exp $ |
17 | 17 | */
|
18 | 18 |
|
19 | 19 | #include"postgres.h"
|
|
26 | 26 | #include"libpq/pqformat.h"
|
27 | 27 | #include"utils/builtins.h"
|
28 | 28 | #include"utils/cash.h"
|
| 29 | +#include"utils/numeric.h" |
29 | 30 | #include"utils/pg_locale.h"
|
30 | 31 |
|
31 | 32 | #defineCASH_BUFSZ36
|
@@ -114,7 +115,6 @@ cash_in(PG_FUNCTION_ARGS)
|
114 | 115 | psymbol;
|
115 | 116 | constchar*nsymbol,
|
116 | 117 | *csymbol;
|
117 |
| - |
118 | 118 | structlconv*lconvert=PGLC_localeconv();
|
119 | 119 |
|
120 | 120 | /*
|
@@ -263,7 +263,6 @@ cash_out(PG_FUNCTION_ARGS)
|
263 | 263 | *nsymbol;
|
264 | 264 | chardsymbol;
|
265 | 265 | charconvention;
|
266 |
| - |
267 | 266 | structlconv*lconvert=PGLC_localeconv();
|
268 | 267 |
|
269 | 268 | /* see comments about frac_digits in cash_in() */
|
@@ -478,6 +477,26 @@ cash_mi(PG_FUNCTION_ARGS)
|
478 | 477 | }
|
479 | 478 |
|
480 | 479 |
|
| 480 | +/* cash_div_cash() |
| 481 | + * Divide cash by cash, returning float8. |
| 482 | + */ |
| 483 | +Datum |
| 484 | +cash_div_cash(PG_FUNCTION_ARGS) |
| 485 | +{ |
| 486 | +Cashdividend=PG_GETARG_CASH(0); |
| 487 | +Cashdivisor=PG_GETARG_CASH(1); |
| 488 | +float8quotient; |
| 489 | + |
| 490 | +if (divisor==0) |
| 491 | +ereport(ERROR, |
| 492 | +(errcode(ERRCODE_DIVISION_BY_ZERO), |
| 493 | +errmsg("division by zero"))); |
| 494 | + |
| 495 | +quotient= (float8)dividend / (float8)divisor; |
| 496 | +PG_RETURN_FLOAT8(quotient); |
| 497 | +} |
| 498 | + |
| 499 | + |
481 | 500 | /* cash_mul_flt8()
|
482 | 501 | * Multiply cash by float8.
|
483 | 502 | */
|
@@ -845,3 +864,77 @@ cash_words(PG_FUNCTION_ARGS)
|
845 | 864 | /* return as text datum */
|
846 | 865 | PG_RETURN_TEXT_P(cstring_to_text(buf));
|
847 | 866 | }
|
| 867 | + |
| 868 | + |
| 869 | +/* cash_numeric() |
| 870 | + * Convert cash to numeric. |
| 871 | + */ |
| 872 | +Datum |
| 873 | +cash_numeric(PG_FUNCTION_ARGS) |
| 874 | +{ |
| 875 | +Cashmoney=PG_GETARG_CASH(0); |
| 876 | +Numericresult; |
| 877 | +intfpoint; |
| 878 | +int64scale; |
| 879 | +inti; |
| 880 | +Datumamount; |
| 881 | +Datumnumeric_scale; |
| 882 | +Datumquotient; |
| 883 | +structlconv*lconvert=PGLC_localeconv(); |
| 884 | + |
| 885 | +/* see comments about frac_digits in cash_in() */ |
| 886 | +fpoint=lconvert->frac_digits; |
| 887 | +if (fpoint<0||fpoint>10) |
| 888 | +fpoint=2; |
| 889 | + |
| 890 | +/* compute required scale factor */ |
| 891 | +scale=1; |
| 892 | +for (i=0;i<fpoint;i++) |
| 893 | +scale *=10; |
| 894 | + |
| 895 | +/* form the result as money / scale */ |
| 896 | +amount=DirectFunctionCall1(int8_numeric,Int64GetDatum(money)); |
| 897 | +numeric_scale=DirectFunctionCall1(int8_numeric,Int64GetDatum(scale)); |
| 898 | +quotient=DirectFunctionCall2(numeric_div,amount,numeric_scale); |
| 899 | + |
| 900 | +/* forcibly round to exactly the intended number of digits */ |
| 901 | +result=DatumGetNumeric(DirectFunctionCall2(numeric_round, |
| 902 | +quotient, |
| 903 | +Int32GetDatum(fpoint))); |
| 904 | + |
| 905 | +PG_RETURN_NUMERIC(result); |
| 906 | +} |
| 907 | + |
| 908 | +/* numeric_cash() |
| 909 | + * Convert numeric to cash. |
| 910 | + */ |
| 911 | +Datum |
| 912 | +numeric_cash(PG_FUNCTION_ARGS) |
| 913 | +{ |
| 914 | +Datumamount=PG_GETARG_DATUM(0); |
| 915 | +Cashresult; |
| 916 | +intfpoint; |
| 917 | +int64scale; |
| 918 | +inti; |
| 919 | +Datumnumeric_scale; |
| 920 | +structlconv*lconvert=PGLC_localeconv(); |
| 921 | + |
| 922 | +/* see comments about frac_digits in cash_in() */ |
| 923 | +fpoint=lconvert->frac_digits; |
| 924 | +if (fpoint<0||fpoint>10) |
| 925 | +fpoint=2; |
| 926 | + |
| 927 | +/* compute required scale factor */ |
| 928 | +scale=1; |
| 929 | +for (i=0;i<fpoint;i++) |
| 930 | +scale *=10; |
| 931 | + |
| 932 | +/* multiply the input amount by scale factor */ |
| 933 | +numeric_scale=DirectFunctionCall1(int8_numeric,Int64GetDatum(scale)); |
| 934 | +amount=DirectFunctionCall2(numeric_mul,amount,numeric_scale); |
| 935 | + |
| 936 | +/* note that numeric_int8 will round to nearest integer for us */ |
| 937 | +result=DatumGetInt64(DirectFunctionCall1(numeric_int8,amount)); |
| 938 | + |
| 939 | +PG_RETURN_CASH(result); |
| 940 | +} |