diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2000-02-24 02:05:30 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2000-02-24 02:05:30 +0000 |
commit | 9110b33f46bf371909b5366c0e05464ccba6ebd9 (patch) | |
tree | 56d9ea5e2d6c17252f1749bbfddff247740a713e /src/backend/utils/adt/numeric.c | |
parent | 512669db9ee465cf3b2bf9c8817381696aa7c5fb (diff) | |
download | postgresql-9110b33f46bf371909b5366c0e05464ccba6ebd9.tar.gz postgresql-9110b33f46bf371909b5366c0e05464ccba6ebd9.zip |
Add numeric <-> int8 and numeric <-> int2 conversion functions, as well
as a unary minus operator for numeric. Now that long numeric constants
will get converted to NUMERIC in early parsing, it's essential to have
numeric->int8 conversion to avoid 'can't convert' errors on undecorated
int8 constants. Threw in the rest for completeness while I was in the
area.
I did not force an initdb for this, since the system will still run
without the new pg_proc/pg_operator entries. Possibly I should've.
Diffstat (limited to 'src/backend/utils/adt/numeric.c')
-rw-r--r-- | src/backend/utils/adt/numeric.c | 157 |
1 files changed, 153 insertions, 4 deletions
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c index e9443ddd9d3..a3e9a7d54c3 100644 --- a/src/backend/utils/adt/numeric.c +++ b/src/backend/utils/adt/numeric.c @@ -5,7 +5,7 @@ * * 1998 Jan Wieck * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.24 2000/01/20 02:21:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.25 2000/02/24 02:05:30 tgl Exp $ * * ---------- */ @@ -357,7 +357,7 @@ numeric(Numeric num, int32 typmod) /* ---------------------------------------------------------------------- * - * Rounding and the like + * Sign manipulation, rounding and the like * * ---------------------------------------------------------------------- */ @@ -396,6 +396,51 @@ numeric_abs(Numeric num) Numeric +numeric_uminus(Numeric num) +{ + Numeric res; + + /* ---------- + * Handle NULL + * ---------- + */ + if (num == NULL) + return NULL; + + /* ---------- + * Handle NaN + * ---------- + */ + if (NUMERIC_IS_NAN(num)) + return make_result(&const_nan); + + /* ---------- + * Do it the easy way directly on the packed format + * ---------- + */ + res = (Numeric) palloc(num->varlen); + memcpy(res, num, num->varlen); + + /* ---------- + * The packed format is known to be totally zero digit trimmed + * always. So we can identify a ZERO by the fact that there + * are no digits at all. Do nothing to a zero. + * ---------- + */ + if (num->varlen != NUMERIC_HDRSZ) + { + /* Else, flip the sign */ + if (NUMERIC_SIGN(num) == NUMERIC_POS) + res->n_sign_dscale = NUMERIC_NEG | NUMERIC_DSCALE(num); + else + res->n_sign_dscale = NUMERIC_POS | NUMERIC_DSCALE(num); + } + + return res; +} + + +Numeric numeric_sign(Numeric num) { Numeric res; @@ -1465,7 +1510,7 @@ numeric_ln(Numeric num) /* ---------- - * numeric_ln() - + * numeric_log() - * * Compute the logarithm of x in a given base * ---------- @@ -1596,6 +1641,8 @@ numeric_power(Numeric num1, Numeric num2) * * ---------------------------------------------------------------------- */ + + Numeric int4_numeric(int32 val) { @@ -1627,7 +1674,7 @@ numeric_int4(Numeric num) return 0; if (NUMERIC_IS_NAN(num)) - return 0; + elog(ERROR, "Cannot convert NaN to int4"); /* ---------- * Get the number in the variable format so we can round to integer. @@ -1648,6 +1695,108 @@ numeric_int4(Numeric num) Numeric +int8_numeric(int64 *val) +{ + Numeric res; + NumericVar result; + char *tmp; + + init_var(&result); + + tmp = int8out(val); + set_var_from_str(tmp, &result); + res = make_result(&result); + + free_var(&result); + pfree(tmp); + + return res; +} + + +int64 * +numeric_int8(Numeric num) +{ + NumericVar x; + char *str; + int64 *result; + + if (num == NULL) + return NULL; + + if (NUMERIC_IS_NAN(num)) + elog(ERROR, "Cannot convert NaN to int8"); + + /* ---------- + * Get the number in the variable format so we can round to integer. + * ---------- + */ + init_var(&x); + set_var_from_num(num, &x); + + str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */ + + free_var(&x); + + result = int8in(str); + pfree(str); + + return result; +} + + +Numeric +int2_numeric(int16 val) +{ + Numeric res; + NumericVar result; + char *tmp; + + init_var(&result); + + tmp = int2out(val); + set_var_from_str(tmp, &result); + res = make_result(&result); + + free_var(&result); + pfree(tmp); + + return res; +} + + +int16 +numeric_int2(Numeric num) +{ + NumericVar x; + char *str; + int16 result; + + if (num == NULL) + return 0; + + if (NUMERIC_IS_NAN(num)) + elog(ERROR, "Cannot convert NaN to int2"); + + /* ---------- + * Get the number in the variable format so we can round to integer. + * ---------- + */ + init_var(&x); + set_var_from_num(num, &x); + + str = get_str_from_var(&x, 0); /* dscale = 0 produces rounding */ + + free_var(&x); + + result = int2in(str); + pfree(str); + + return result; +} + + +Numeric float8_numeric(float64 val) { Numeric res; |