diff options
| author | Tom Lane | 2003-05-13 18:03:08 +0000 |
|---|---|---|
| committer | Tom Lane | 2003-05-13 18:03:08 +0000 |
| commit | 0249c24235817417a2fa23057822530d81800417 (patch) | |
| tree | 8cd469954fb342476bcc41038515458875b10c1a /src/backend/utils/adt | |
| parent | 72f311b86a50f5e75536db6a0e1b0eaca6baeb4a (diff) | |
More binary I/O routines.
Diffstat (limited to 'src/backend/utils/adt')
| -rw-r--r-- | src/backend/utils/adt/cash.c | 28 | ||||
| -rw-r--r-- | src/backend/utils/adt/geo_ops.c | 267 | ||||
| -rw-r--r-- | src/backend/utils/adt/mac.c | 47 | ||||
| -rw-r--r-- | src/backend/utils/adt/network.c | 98 | ||||
| -rw-r--r-- | src/backend/utils/adt/pseudotypes.c | 59 |
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. |
