diff options
author | Robert Haas <rhaas@postgresql.org> | 2011-04-05 09:35:43 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2011-04-05 09:35:43 -0400 |
commit | f5e524d92be609c709825be8995bf77f10880c3b (patch) | |
tree | 6b3a1754ad3c06f1146a632a77fcc56c7d23e1d1 /src | |
parent | 88f32b7ca29982f286b61a9d0dd29be4b8a01c25 (diff) | |
download | postgresql-f5e524d92be609c709825be8995bf77f10880c3b.tar.gz postgresql-f5e524d92be609c709825be8995bf77f10880c3b.zip |
Add casts from int4 and int8 to numeric.
Joey Adams, per gripe from Ramanujam. Review by myself and Tom Lane.
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/utils/adt/cash.c | 62 | ||||
-rw-r--r-- | src/include/catalog/catversion.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_cast.h | 2 | ||||
-rw-r--r-- | src/include/catalog/pg_proc.h | 4 | ||||
-rw-r--r-- | src/include/utils/cash.h | 3 | ||||
-rw-r--r-- | src/test/regress/expected/money.out | 63 | ||||
-rw-r--r-- | src/test/regress/sql/money.sql | 15 |
7 files changed, 149 insertions, 2 deletions
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c index 67f51280c38..4c3279759d5 100644 --- a/src/backend/utils/adt/cash.c +++ b/src/backend/utils/adt/cash.c @@ -26,6 +26,7 @@ #include "libpq/pqformat.h" #include "utils/builtins.h" #include "utils/cash.h" +#include "utils/int8.h" #include "utils/numeric.h" #include "utils/pg_locale.h" @@ -92,7 +93,6 @@ num_word(Cash value) return buf; } /* num_word() */ - /* cash_in() * Convert a string to a cash data type. * Format is [$]###[,]###[.##] @@ -938,3 +938,63 @@ numeric_cash(PG_FUNCTION_ARGS) PG_RETURN_CASH(result); } + +/* int4_cash() + * Convert int4 (int) to cash + */ +Datum +int4_cash(PG_FUNCTION_ARGS) +{ + int32 amount = PG_GETARG_INT32(0); + Cash result; + int fpoint; + int64 scale; + int i; + struct lconv *lconvert = PGLC_localeconv(); + + /* see comments about frac_digits in cash_in() */ + fpoint = lconvert->frac_digits; + if (fpoint < 0 || fpoint > 10) + fpoint = 2; + + /* compute required scale factor */ + scale = 1; + for (i = 0; i < fpoint; i++) + scale *= 10; + + /* compute amount * scale, checking for overflow */ + result = DatumGetInt64(DirectFunctionCall2(int8mul, Int64GetDatum(amount), + Int64GetDatum(scale))); + + PG_RETURN_CASH(result); +} + +/* int8_cash() + * Convert int8 (bigint) to cash + */ +Datum +int8_cash(PG_FUNCTION_ARGS) +{ + int64 amount = PG_GETARG_INT64(0); + Cash result; + int fpoint; + int64 scale; + int i; + struct lconv *lconvert = PGLC_localeconv(); + + /* see comments about frac_digits in cash_in() */ + fpoint = lconvert->frac_digits; + if (fpoint < 0 || fpoint > 10) + fpoint = 2; + + /* compute required scale factor */ + scale = 1; + for (i = 0; i < fpoint; i++) + scale *= 10; + + /* compute amount * scale, checking for overflow */ + result = DatumGetInt64(DirectFunctionCall2(int8mul, Int64GetDatum(amount), + Int64GetDatum(scale))); + + PG_RETURN_CASH(result); +} diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index e9659092198..b74526b3b79 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201103201 +#define CATALOG_VERSION_NO 201104051 #endif diff --git a/src/include/catalog/pg_cast.h b/src/include/catalog/pg_cast.h index bf8a6fcb77d..f7b7b768330 100644 --- a/src/include/catalog/pg_cast.h +++ b/src/include/catalog/pg_cast.h @@ -126,6 +126,8 @@ DATA(insert ( 1700 700 1745 i f )); DATA(insert ( 1700 701 1746 i f )); DATA(insert ( 790 1700 3823 a f )); DATA(insert ( 1700 790 3824 a f )); +DATA(insert ( 23 790 3811 a f )); +DATA(insert ( 20 790 3812 a f )); /* Allow explicit coercions between int4 and bool */ DATA(insert ( 23 16 2557 e f )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index cff64ba6b02..7919a40487f 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -971,6 +971,10 @@ DATA(insert OID = 3823 ( numeric PGNSP PGUID 12 1 0 0 f f f t f s 1 0 1700 DESCR("convert money to numeric"); DATA(insert OID = 3824 ( money PGNSP PGUID 12 1 0 0 f f f t f s 1 0 790 "1700" _null_ _null_ _null_ _null_ numeric_cash _null_ _null_ _null_ )); DESCR("convert numeric to money"); +DATA(insert OID = 3811 ( money PGNSP PGUID 12 1 0 0 f f f t f s 1 0 790 "23" _null_ _null_ _null_ _null_ int4_cash _null_ _null_ _null_ )); +DESCR("convert int4 to money"); +DATA(insert OID = 3812 ( money PGNSP PGUID 12 1 0 0 f f f t f s 1 0 790 "20" _null_ _null_ _null_ _null_ int8_cash _null_ _null_ _null_ )); +DESCR("convert int8 to money"); /* OIDS 900 - 999 */ diff --git a/src/include/utils/cash.h b/src/include/utils/cash.h index 81b51ad68f1..3a491f9231a 100644 --- a/src/include/utils/cash.h +++ b/src/include/utils/cash.h @@ -67,4 +67,7 @@ extern Datum cash_words(PG_FUNCTION_ARGS); extern Datum cash_numeric(PG_FUNCTION_ARGS); extern Datum numeric_cash(PG_FUNCTION_ARGS); +extern Datum int4_cash(PG_FUNCTION_ARGS); +extern Datum int8_cash(PG_FUNCTION_ARGS); + #endif /* CASH_H */ diff --git a/src/test/regress/expected/money.out b/src/test/regress/expected/money.out index ec4169cbb06..538235c4cc2 100644 --- a/src/test/regress/expected/money.out +++ b/src/test/regress/expected/money.out @@ -185,3 +185,66 @@ SELECT * FROM money_data; $123.46 (1 row) +-- Cast int4/int8 to money +SELECT 1234567890::money; + money +------------------- + $1,234,567,890.00 +(1 row) + +SELECT 12345678901234567::money; + money +---------------------------- + $12,345,678,901,234,567.00 +(1 row) + +SELECT 123456789012345678::money; +ERROR: bigint out of range +SELECT 9223372036854775807::money; +ERROR: bigint out of range +SELECT (-12345)::money; + money +------------- + -$12,345.00 +(1 row) + +SELECT (-1234567890)::money; + money +-------------------- + -$1,234,567,890.00 +(1 row) + +SELECT (-12345678901234567)::money; + money +----------------------------- + -$12,345,678,901,234,567.00 +(1 row) + +SELECT (-123456789012345678)::money; +ERROR: bigint out of range +SELECT (-9223372036854775808)::money; +ERROR: bigint out of range +SELECT 1234567890::int4::money; + money +------------------- + $1,234,567,890.00 +(1 row) + +SELECT 12345678901234567::int8::money; + money +---------------------------- + $12,345,678,901,234,567.00 +(1 row) + +SELECT (-1234567890)::int4::money; + money +-------------------- + -$1,234,567,890.00 +(1 row) + +SELECT (-12345678901234567)::int8::money; + money +----------------------------- + -$12,345,678,901,234,567.00 +(1 row) + diff --git a/src/test/regress/sql/money.sql b/src/test/regress/sql/money.sql index 580425e5043..09b9476b706 100644 --- a/src/test/regress/sql/money.sql +++ b/src/test/regress/sql/money.sql @@ -56,3 +56,18 @@ SELECT * FROM money_data; DELETE FROM money_data; INSERT INTO money_data VALUES ('$123.459'); SELECT * FROM money_data; + +-- Cast int4/int8 to money +SELECT 1234567890::money; +SELECT 12345678901234567::money; +SELECT 123456789012345678::money; +SELECT 9223372036854775807::money; +SELECT (-12345)::money; +SELECT (-1234567890)::money; +SELECT (-12345678901234567)::money; +SELECT (-123456789012345678)::money; +SELECT (-9223372036854775808)::money; +SELECT 1234567890::int4::money; +SELECT 12345678901234567::int8::money; +SELECT (-1234567890)::int4::money; +SELECT (-12345678901234567)::int8::money; |