summaryrefslogtreecommitdiff
path: root/src/backend/utils/adt
diff options
context:
space:
mode:
authorTom Lane2003-05-13 18:03:08 +0000
committerTom Lane2003-05-13 18:03:08 +0000
commit0249c24235817417a2fa23057822530d81800417 (patch)
tree8cd469954fb342476bcc41038515458875b10c1a /src/backend/utils/adt
parent72f311b86a50f5e75536db6a0e1b0eaca6baeb4a (diff)
More binary I/O routines.
Diffstat (limited to 'src/backend/utils/adt')
-rw-r--r--src/backend/utils/adt/cash.c28
-rw-r--r--src/backend/utils/adt/geo_ops.c267
-rw-r--r--src/backend/utils/adt/mac.c47
-rw-r--r--src/backend/utils/adt/network.c98
-rw-r--r--src/backend/utils/adt/pseudotypes.c59
5 files changed, 493 insertions, 6 deletions
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c
index f210f4258f0..4a4e13117ef 100644
--- a/src/backend/utils/adt/cash.c
+++ b/src/backend/utils/adt/cash.c
@@ -9,7 +9,7 @@
* workings can be found in the book "Software Solutions in C" by
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.57 2003/03/11 21:01:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.58 2003/05/13 18:03:07 tgl Exp $
*/
#include "postgres.h"
@@ -19,6 +19,7 @@
#include <math.h>
#include <locale.h>
+#include "libpq/pqformat.h"
#include "miscadmin.h"
#include "utils/builtins.h"
#include "utils/cash.h"
@@ -310,6 +311,31 @@ cash_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(result);
}
+/*
+ * cash_recv - converts external binary format to cash
+ */
+Datum
+cash_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+
+ PG_RETURN_CASH((Cash) pq_getmsgint(buf, sizeof(Cash)));
+}
+
+/*
+ * cash_send - converts cash to binary format
+ */
+Datum
+cash_send(PG_FUNCTION_ARGS)
+{
+ Cash arg1 = PG_GETARG_CASH(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendint(&buf, arg1, sizeof(Cash));
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
Datum
cash_eq(PG_FUNCTION_ARGS)
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 956bd1753f6..1412a1c6821 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.76 2003/05/09 21:19:49 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.77 2003/05/13 18:03:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -409,6 +409,58 @@ box_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(path_encode(-1, 2, &(box->high)));
}
+/*
+ * box_recv - converts external binary format to box
+ */
+Datum
+box_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ BOX *box;
+ double x,
+ y;
+
+ box = (BOX *) palloc(sizeof(BOX));
+
+ box->high.x = pq_getmsgfloat8(buf);
+ box->high.y = pq_getmsgfloat8(buf);
+ box->low.x = pq_getmsgfloat8(buf);
+ box->low.y = pq_getmsgfloat8(buf);
+
+ /* reorder corners if necessary... */
+ if (box->high.x < box->low.x)
+ {
+ x = box->high.x;
+ box->high.x = box->low.x;
+ box->low.x = x;
+ }
+ if (box->high.y < box->low.y)
+ {
+ y = box->high.y;
+ box->high.y = box->low.y;
+ box->low.y = y;
+ }
+
+ PG_RETURN_BOX_P(box);
+}
+
+/*
+ * box_send - converts box to binary format
+ */
+Datum
+box_send(PG_FUNCTION_ARGS)
+{
+ BOX *box = PG_GETARG_BOX_P(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendfloat8(&buf, box->high.x);
+ pq_sendfloat8(&buf, box->high.y);
+ pq_sendfloat8(&buf, box->low.x);
+ pq_sendfloat8(&buf, box->low.y);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
/* box_construct - fill in a new box.
*/
@@ -915,6 +967,26 @@ line_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(result);
}
+/*
+ * line_recv - converts external binary format to line
+ */
+Datum
+line_recv(PG_FUNCTION_ARGS)
+{
+ elog(ERROR, "line not yet implemented");
+ return 0;
+}
+
+/*
+ * line_send - converts line to binary format
+ */
+Datum
+line_send(PG_FUNCTION_ARGS)
+{
+ elog(ERROR, "line not yet implemented");
+ return 0;
+}
+
/*----------------------------------------------------------
* Conversion routines from one line formula to internal.
@@ -1271,6 +1343,64 @@ path_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(path_encode(path->closed, path->npts, path->p));
}
+/*
+ * path_recv - converts external binary format to path
+ *
+ * External representation is closed flag (a boolean byte), int32 number
+ * of points, and the points.
+ */
+Datum
+path_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ PATH *path;
+ int closed;
+ int32 npts;
+ int32 i;
+ int size;
+
+ closed = pq_getmsgbyte(buf);
+ npts = pq_getmsgint(buf, sizeof(int32));
+ if (npts < 0 || npts >= (int32) (INT_MAX / sizeof(Point)))
+ elog(ERROR, "Invalid number of points in external path");
+
+ size = offsetof(PATH, p[0]) +sizeof(path->p[0]) * npts;
+ path = (PATH *) palloc(size);
+
+ path->size = size;
+ path->npts = npts;
+ path->closed = (closed ? 1 : 0);
+
+ for (i = 0; i < npts; i++)
+ {
+ path->p[i].x = pq_getmsgfloat8(buf);
+ path->p[i].y = pq_getmsgfloat8(buf);
+ }
+
+ PG_RETURN_PATH_P(path);
+}
+
+/*
+ * path_send - converts path to binary format
+ */
+Datum
+path_send(PG_FUNCTION_ARGS)
+{
+ PATH *path = PG_GETARG_PATH_P(0);
+ StringInfoData buf;
+ int32 i;
+
+ pq_begintypsend(&buf);
+ pq_sendbyte(&buf, path->closed ? 1 : 0);
+ pq_sendint(&buf, path->npts, sizeof(int32));
+ for (i = 0; i < path->npts; i++)
+ {
+ pq_sendfloat8(&buf, path->p[i].x);
+ pq_sendfloat8(&buf, path->p[i].y);
+ }
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
/*----------------------------------------------------------
* Relational operators.
@@ -1815,6 +1945,46 @@ lseg_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(path_encode(FALSE, 2, (Point *) &(ls->p[0])));
}
+/*
+ * lseg_recv - converts external binary format to lseg
+ */
+Datum
+lseg_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ LSEG *lseg;
+
+ lseg = (LSEG *) palloc(sizeof(LSEG));
+
+ lseg->p[0].x = pq_getmsgfloat8(buf);
+ lseg->p[0].y = pq_getmsgfloat8(buf);
+ lseg->p[1].x = pq_getmsgfloat8(buf);
+ lseg->p[1].y = pq_getmsgfloat8(buf);
+
+#ifdef NOT_USED
+ lseg->m = point_sl(&lseg->p[0], &lseg->p[1]);
+#endif
+
+ PG_RETURN_LSEG_P(lseg);
+}
+
+/*
+ * lseg_send - converts lseg to binary format
+ */
+Datum
+lseg_send(PG_FUNCTION_ARGS)
+{
+ LSEG *ls = PG_GETARG_LSEG_P(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendfloat8(&buf, ls->p[0].x);
+ pq_sendfloat8(&buf, ls->p[0].y);
+ pq_sendfloat8(&buf, ls->p[1].x);
+ pq_sendfloat8(&buf, ls->p[1].y);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
/* lseg_construct -
* form a LSEG from two Points.
@@ -3186,6 +3356,64 @@ poly_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(path_encode(TRUE, poly->npts, poly->p));
}
+/*
+ * poly_recv - converts external binary format to polygon
+ *
+ * External representation is int32 number of points, and the points.
+ * We recompute the bounding box on read, instead of trusting it to
+ * be valid. (Checking it would take just as long, so may as well
+ * omit it from external representation.)
+ */
+Datum
+poly_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ POLYGON *poly;
+ int32 npts;
+ int32 i;
+ int size;
+
+ npts = pq_getmsgint(buf, sizeof(int32));
+ if (npts < 0 || npts >= (int32) ((INT_MAX - offsetof(POLYGON, p[0])) / sizeof(Point)))
+ elog(ERROR, "Invalid number of points in external polygon");
+
+ size = offsetof(POLYGON, p[0]) +sizeof(poly->p[0]) * npts;
+ poly = (POLYGON *) palloc0(size); /* zero any holes */
+
+ poly->size = size;
+ poly->npts = npts;
+
+ for (i = 0; i < npts; i++)
+ {
+ poly->p[i].x = pq_getmsgfloat8(buf);
+ poly->p[i].y = pq_getmsgfloat8(buf);
+ }
+
+ make_bound_box(poly);
+
+ PG_RETURN_POLYGON_P(poly);
+}
+
+/*
+ * poly_send - converts polygon to binary format
+ */
+Datum
+poly_send(PG_FUNCTION_ARGS)
+{
+ POLYGON *poly = PG_GETARG_POLYGON_P(0);
+ StringInfoData buf;
+ int32 i;
+
+ pq_begintypsend(&buf);
+ pq_sendint(&buf, poly->npts, sizeof(int32));
+ for (i = 0; i < poly->npts; i++)
+ {
+ pq_sendfloat8(&buf, poly->p[i].x);
+ pq_sendfloat8(&buf, poly->p[i].y);
+ }
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
/*-------------------------------------------------------
* Is polygon A strictly left of polygon B? i.e. is
@@ -4001,6 +4229,43 @@ circle_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(result);
}
+/*
+ * circle_recv - converts external binary format to circle
+ */
+Datum
+circle_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ CIRCLE *circle;
+
+ circle = (CIRCLE *) palloc(sizeof(CIRCLE));
+
+ circle->center.x = pq_getmsgfloat8(buf);
+ circle->center.y = pq_getmsgfloat8(buf);
+ circle->radius = pq_getmsgfloat8(buf);
+
+ if (circle->radius < 0)
+ elog(ERROR, "Invalid radius in external circle");
+
+ PG_RETURN_CIRCLE_P(circle);
+}
+
+/*
+ * circle_send - converts circle to binary format
+ */
+Datum
+circle_send(PG_FUNCTION_ARGS)
+{
+ CIRCLE *circle = PG_GETARG_CIRCLE_P(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendfloat8(&buf, circle->center.x);
+ pq_sendfloat8(&buf, circle->center.y);
+ pq_sendfloat8(&buf, circle->radius);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
/*----------------------------------------------------------
* Relational operators for CIRCLEs.
diff --git a/src/backend/utils/adt/mac.c b/src/backend/utils/adt/mac.c
index ba15342739d..01111e3c2fb 100644
--- a/src/backend/utils/adt/mac.c
+++ b/src/backend/utils/adt/mac.c
@@ -1,15 +1,17 @@
/*
* PostgreSQL type definitions for MAC addresses.
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/mac.c,v 1.27 2002/10/13 15:39:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/mac.c,v 1.28 2003/05/13 18:03:07 tgl Exp $
*/
#include "postgres.h"
#include "access/hash.h"
+#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/inet.h"
+
/*
* Utility macros used for sorting and comparing:
*/
@@ -96,6 +98,49 @@ macaddr_out(PG_FUNCTION_ARGS)
}
/*
+ * macaddr_recv - converts external binary format to macaddr
+ *
+ * The external representation is just the six bytes, MSB first.
+ */
+Datum
+macaddr_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ macaddr *addr;
+
+ addr = (macaddr *) palloc(sizeof(macaddr));
+
+ addr->a = pq_getmsgbyte(buf);
+ addr->b = pq_getmsgbyte(buf);
+ addr->c = pq_getmsgbyte(buf);
+ addr->d = pq_getmsgbyte(buf);
+ addr->e = pq_getmsgbyte(buf);
+ addr->f = pq_getmsgbyte(buf);
+
+ PG_RETURN_MACADDR_P(addr);
+}
+
+/*
+ * macaddr_send - converts macaddr to binary format
+ */
+Datum
+macaddr_send(PG_FUNCTION_ARGS)
+{
+ macaddr *addr = PG_GETARG_MACADDR_P(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendbyte(&buf, addr->a);
+ pq_sendbyte(&buf, addr->b);
+ pq_sendbyte(&buf, addr->c);
+ pq_sendbyte(&buf, addr->d);
+ pq_sendbyte(&buf, addr->e);
+ pq_sendbyte(&buf, addr->f);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+
+/*
* Convert macaddr to text data type.
*/
diff --git a/src/backend/utils/adt/network.c b/src/backend/utils/adt/network.c
index d814f96731d..3bc645c988b 100644
--- a/src/backend/utils/adt/network.c
+++ b/src/backend/utils/adt/network.c
@@ -3,7 +3,7 @@
* is for IP V4 CIDR notation, but prepared for V6: just
* add the necessary bits where the comments indicate.
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/network.c,v 1.40 2003/03/21 23:18:52 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/network.c,v 1.41 2003/05/13 18:03:07 tgl Exp $
*
* Jon Postel RIP 16 Oct 1998
*/
@@ -16,6 +16,7 @@
#include <arpa/inet.h>
#include "catalog/pg_type.h"
+#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/inet.h"
@@ -148,6 +149,101 @@ cidr_out(PG_FUNCTION_ARGS)
}
+/*
+ * inet_recv - converts external binary format to inet
+ *
+ * The external representation is (one byte apiece for)
+ * family, bits, type, address length, address in network byte order.
+ */
+Datum
+inet_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ inet *addr;
+ char *addrptr;
+ int bits;
+ int nb,
+ i;
+
+ /* make sure any unused bits in a CIDR value are zeroed */
+ addr = (inet *) palloc0(VARHDRSZ + sizeof(inet_struct));
+
+ ip_family(addr) = pq_getmsgbyte(buf);
+ if (ip_family(addr) != AF_INET)
+ elog(ERROR, "Invalid family in external inet");
+ bits = pq_getmsgbyte(buf);
+ if (bits < 0 || bits > 32)
+ elog(ERROR, "Invalid bits in external inet");
+ ip_bits(addr) = bits;
+ ip_type(addr) = pq_getmsgbyte(buf);
+ if (ip_type(addr) != 0 && ip_type(addr) != 1)
+ elog(ERROR, "Invalid type in external inet");
+ nb = pq_getmsgbyte(buf);
+ if (nb != ip_addrsize(addr))
+ elog(ERROR, "Invalid length in external inet");
+
+ VARATT_SIZEP(addr) = VARHDRSZ
+ + ((char *) &ip_v4addr(addr) - (char *) VARDATA(addr))
+ + ip_addrsize(addr);
+
+ addrptr = (char *) &ip_v4addr(addr);
+ for (i = 0; i < nb; i++)
+ addrptr[i] = pq_getmsgbyte(buf);
+
+ /*
+ * Error check: CIDR values must not have any bits set beyond the
+ * masklen. XXX this code is not IPV6 ready.
+ */
+ if (ip_type(addr))
+ {
+ if (!v4addressOK(ip_v4addr(addr), bits))
+ elog(ERROR, "invalid external CIDR value: has bits set to right of mask");
+ }
+
+ PG_RETURN_INET_P(addr);
+}
+
+/* share code with INET case */
+Datum
+cidr_recv(PG_FUNCTION_ARGS)
+{
+ return inet_recv(fcinfo);
+}
+
+/*
+ * inet_send - converts inet to binary format
+ */
+Datum
+inet_send(PG_FUNCTION_ARGS)
+{
+ inet *addr = PG_GETARG_INET_P(0);
+ StringInfoData buf;
+ char *addrptr;
+ int nb,
+ i;
+
+ pq_begintypsend(&buf);
+ pq_sendbyte(&buf, ip_family(addr));
+ pq_sendbyte(&buf, ip_bits(addr));
+ pq_sendbyte(&buf, ip_type(addr));
+ nb = ip_addrsize(addr);
+ if (nb < 0)
+ nb = 0;
+ pq_sendbyte(&buf, nb);
+ addrptr = (char *) &ip_v4addr(addr);
+ for (i = 0; i < nb; i++)
+ pq_sendbyte(&buf, addrptr[i]);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+/* share code with INET case */
+Datum
+cidr_send(PG_FUNCTION_ARGS)
+{
+ return inet_send(fcinfo);
+}
+
+
static Datum
text_network(text *src, int type)
{
diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c
index 59b31859189..1a997ed9779 100644
--- a/src/backend/utils/adt/pseudotypes.c
+++ b/src/backend/utils/adt/pseudotypes.c
@@ -16,12 +16,13 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/pseudotypes.c,v 1.6 2003/05/08 22:19:56 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/pseudotypes.c,v 1.7 2003/05/13 18:03:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
+#include "libpq/pqformat.h"
#include "utils/array.h"
#include "utils/builtins.h"
@@ -54,7 +55,7 @@ record_out(PG_FUNCTION_ARGS)
Datum
record_recv(PG_FUNCTION_ARGS)
{
- elog(ERROR, "Cannot accept a constant of type %s", "RECORD");
+ elog(ERROR, "Cannot accept a value of type %s", "RECORD");
PG_RETURN_VOID(); /* keep compiler quiet */
}
@@ -98,6 +99,34 @@ cstring_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(pstrdup(str));
}
+/*
+ * cstring_recv - binary input routine for pseudo-type CSTRING.
+ */
+Datum
+cstring_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ char *str;
+ int nbytes;
+
+ str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+ PG_RETURN_CSTRING(str);
+}
+
+/*
+ * cstring_send - binary output routine for pseudo-type CSTRING.
+ */
+Datum
+cstring_send(PG_FUNCTION_ARGS)
+{
+ char *str = PG_GETARG_CSTRING(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendtext(&buf, str, strlen(str));
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
/*
* any_in - input routine for pseudo-type ANY.
@@ -144,6 +173,32 @@ anyarray_out(PG_FUNCTION_ARGS)
return array_out(fcinfo);
}
+/*
+ * anyarray_recv - binary input routine for pseudo-type ANYARRAY.
+ *
+ * XXX this could actually be made to work, since the incoming array
+ * data will contain the element type OID. Need to think through
+ * type-safety issues before allowing it, however.
+ */
+Datum
+anyarray_recv(PG_FUNCTION_ARGS)
+{
+ elog(ERROR, "Cannot accept a value of type %s", "ANYARRAY");
+
+ PG_RETURN_VOID(); /* keep compiler quiet */
+}
+
+/*
+ * anyarray_send - binary output routine for pseudo-type ANYARRAY.
+ *
+ * We may as well allow this, since array_send will in fact work.
+ */
+Datum
+anyarray_send(PG_FUNCTION_ARGS)
+{
+ return array_send(fcinfo);
+}
+
/*
* void_in - input routine for pseudo-type VOID.