aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt/numeric.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt/numeric.c')
-rw-r--r--src/backend/utils/adt/numeric.c76
1 files changed, 75 insertions, 1 deletions
diff --git a/src/backend/utils/adt/numeric.c b/src/backend/utils/adt/numeric.c
index c851ae5eb35..f67deb281ab 100644
--- a/src/backend/utils/adt/numeric.c
+++ b/src/backend/utils/adt/numeric.c
@@ -14,7 +14,7 @@
* Copyright (c) 1998-2003, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.60 2003/04/21 00:22:24 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.61 2003/05/12 23:08:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,6 +28,7 @@
#include <errno.h>
#include "catalog/pg_type.h"
+#include "libpq/pqformat.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/int8.h"
@@ -370,6 +371,79 @@ numeric_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(str);
}
+/*
+ * numeric_recv - converts external binary format to numeric
+ *
+ * External format is a sequence of int16's:
+ * ndigits, weight, sign, dscale, NumericDigits.
+ */
+Datum
+numeric_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ NumericVar value;
+ Numeric res;
+ int len,
+ i;
+
+ init_var(&value);
+
+ len = (uint16) pq_getmsgint(buf, sizeof(uint16));
+ if (len < 0 || len > NUMERIC_MAX_PRECISION + NUMERIC_MAX_RESULT_SCALE)
+ elog(ERROR, "Invalid length in external numeric");
+
+ alloc_var(&value, len);
+
+ value.weight = (int16) pq_getmsgint(buf, sizeof(int16));
+ value.sign = (uint16) pq_getmsgint(buf, sizeof(uint16));
+ if (!(value.sign == NUMERIC_POS ||
+ value.sign == NUMERIC_NEG ||
+ value.sign == NUMERIC_NAN))
+ elog(ERROR, "Invalid sign in external numeric");
+ value.dscale = (uint16) pq_getmsgint(buf, sizeof(uint16));
+ for (i = 0; i < len; i++)
+ {
+ NumericDigit d = pq_getmsgint(buf, sizeof(NumericDigit));
+
+ if (d < 0 || d >= NBASE)
+ elog(ERROR, "Invalid digit in external numeric");
+ value.digits[i] = d;
+ }
+
+ res = make_result(&value);
+ free_var(&value);
+
+ PG_RETURN_NUMERIC(res);
+}
+
+/*
+ * numeric_send - converts numeric to binary format
+ */
+Datum
+numeric_send(PG_FUNCTION_ARGS)
+{
+ Numeric num = PG_GETARG_NUMERIC(0);
+ NumericVar x;
+ StringInfoData buf;
+ int i;
+
+ init_var(&x);
+ set_var_from_num(num, &x);
+
+ pq_begintypsend(&buf);
+
+ pq_sendint(&buf, x.ndigits, sizeof(int16));
+ pq_sendint(&buf, x.weight, sizeof(int16));
+ pq_sendint(&buf, x.sign, sizeof(int16));
+ pq_sendint(&buf, x.dscale, sizeof(int16));
+ for (i = 0; i < x.ndigits; i++)
+ pq_sendint(&buf, x.digits[i], sizeof(NumericDigit));
+
+ free_var(&x);
+
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
/*
* numeric() -