mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Add casts from int4 and int8 to numeric.
Joey Adams, per gripe from Ramanujam. Review by myself and Tom Lane.
This commit is contained in:
parent
88f32b7ca2
commit
f5e524d92b
@ -886,15 +886,22 @@ ALTER SEQUENCE <replaceable class="parameter">tablename</replaceable>_<replaceab
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Values of the <type>numeric</type> data type can be cast to
|
Values of the <type>numeric</type>, <type>int</type>, and
|
||||||
<type>money</type>. Other numeric types can be converted to
|
<type>bigint</type> data types can be cast to <type>money</type>.
|
||||||
<type>money</type> by casting to <type>numeric</type> first, for example:
|
Conversion from the <type>real</type> and <type>double precision</type>
|
||||||
|
data types can be done by casting to <type>numeric</type> first, for
|
||||||
|
example:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
SELECT 1234::numeric::money;
|
SELECT '12.34'::float8::numeric::money;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
However, this is not recommended. Floating point numbers should not be
|
||||||
|
used to handle money due to the potential for rounding errors.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
A <type>money</type> value can be cast to <type>numeric</type> without
|
A <type>money</type> value can be cast to <type>numeric</type> without
|
||||||
loss of precision. Conversion to other types could potentially lose
|
loss of precision. Conversion to other types could potentially lose
|
||||||
precision, and it must be done in two stages, for example:
|
precision, and must also be done in two stages:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
SELECT '52093.89'::money::numeric::float8;
|
SELECT '52093.89'::money::numeric::float8;
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "libpq/pqformat.h"
|
#include "libpq/pqformat.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/cash.h"
|
#include "utils/cash.h"
|
||||||
|
#include "utils/int8.h"
|
||||||
#include "utils/numeric.h"
|
#include "utils/numeric.h"
|
||||||
#include "utils/pg_locale.h"
|
#include "utils/pg_locale.h"
|
||||||
|
|
||||||
@ -92,7 +93,6 @@ num_word(Cash value)
|
|||||||
return buf;
|
return buf;
|
||||||
} /* num_word() */
|
} /* num_word() */
|
||||||
|
|
||||||
|
|
||||||
/* cash_in()
|
/* cash_in()
|
||||||
* Convert a string to a cash data type.
|
* Convert a string to a cash data type.
|
||||||
* Format is [$]###[,]###[.##]
|
* Format is [$]###[,]###[.##]
|
||||||
@ -938,3 +938,63 @@ numeric_cash(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
PG_RETURN_CASH(result);
|
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);
|
||||||
|
}
|
||||||
|
@ -53,6 +53,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* yyyymmddN */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 201103201
|
#define CATALOG_VERSION_NO 201104051
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -126,6 +126,8 @@ DATA(insert ( 1700 700 1745 i f ));
|
|||||||
DATA(insert ( 1700 701 1746 i f ));
|
DATA(insert ( 1700 701 1746 i f ));
|
||||||
DATA(insert ( 790 1700 3823 a f ));
|
DATA(insert ( 790 1700 3823 a f ));
|
||||||
DATA(insert ( 1700 790 3824 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 */
|
/* Allow explicit coercions between int4 and bool */
|
||||||
DATA(insert ( 23 16 2557 e f ));
|
DATA(insert ( 23 16 2557 e f ));
|
||||||
|
@ -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");
|
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_ ));
|
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");
|
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 */
|
/* OIDS 900 - 999 */
|
||||||
|
|
||||||
|
@ -67,4 +67,7 @@ extern Datum cash_words(PG_FUNCTION_ARGS);
|
|||||||
extern Datum cash_numeric(PG_FUNCTION_ARGS);
|
extern Datum cash_numeric(PG_FUNCTION_ARGS);
|
||||||
extern Datum numeric_cash(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 */
|
#endif /* CASH_H */
|
||||||
|
@ -185,3 +185,66 @@ SELECT * FROM money_data;
|
|||||||
$123.46
|
$123.46
|
||||||
(1 row)
|
(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)
|
||||||
|
|
||||||
|
@ -56,3 +56,18 @@ SELECT * FROM money_data;
|
|||||||
DELETE FROM money_data;
|
DELETE FROM money_data;
|
||||||
INSERT INTO money_data VALUES ('$123.459');
|
INSERT INTO money_data VALUES ('$123.459');
|
||||||
SELECT * FROM money_data;
|
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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user