aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/copy.c372
-rw-r--r--src/backend/libpq/pqformat.c143
-rw-r--r--src/backend/utils/adt/float.c61
-rw-r--r--src/backend/utils/adt/geo_ops.c34
-rw-r--r--src/backend/utils/adt/name.c69
-rw-r--r--src/include/catalog/catversion.h4
-rw-r--r--src/include/catalog/pg_proc.h18
-rw-r--r--src/include/catalog/pg_type.h12
-rw-r--r--src/include/libpq/pqformat.h6
-rw-r--r--src/include/utils/builtins.h8
-rw-r--r--src/include/utils/geo_decls.h4
11 files changed, 491 insertions, 240 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 06c29c4894b..20a46cc9229 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.199 2003/05/09 18:08:48 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.200 2003/05/09 21:19:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -17,6 +17,8 @@
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
#include "access/genam.h"
#include "access/heapam.h"
@@ -88,13 +90,13 @@ static void CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print);
static void CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
char *delim, char *null_print);
-static Oid GetInputFunction(Oid type);
-static Oid GetTypeElement(Oid type);
static char *CopyReadAttribute(const char *delim, CopyReadResult *result);
+static Datum CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo,
+ Oid typelem, bool *isnull);
static void CopyAttributeOut(char *string, char *delim);
static List *CopyGetAttnums(Relation rel, List *attnamelist);
-static const char BinarySignature[12] = "PGBCOPY\n\377\r\n\0";
+static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
/*
* Static communication variables ... pretty grotty, but COPY has
@@ -137,6 +139,10 @@ static int CopyGetChar(void);
#define CopyGetEof() (fe_eof)
static int CopyPeekChar(void);
static void CopyDonePeek(int c, bool pickup);
+static void CopySendInt32(int32 val);
+static int32 CopyGetInt32(void);
+static void CopySendInt16(int16 val);
+static int16 CopyGetInt16(void);
/*
* Send copy start/stop messages for frontend copies. These have changed
@@ -519,6 +525,58 @@ CopyDonePeek(int c, bool pickup)
}
+/*
+ * These functions do apply some data conversion
+ */
+
+/*
+ * CopySendInt32 sends an int32 in network byte order
+ */
+static void
+CopySendInt32(int32 val)
+{
+ uint32 buf;
+
+ buf = htonl((uint32) val);
+ CopySendData(&buf, sizeof(buf));
+}
+
+/*
+ * CopyGetInt32 reads an int32 that appears in network byte order
+ */
+static int32
+CopyGetInt32(void)
+{
+ uint32 buf;
+
+ CopyGetData(&buf, sizeof(buf));
+ return (int32) ntohl(buf);
+}
+
+/*
+ * CopySendInt16 sends an int16 in network byte order
+ */
+static void
+CopySendInt16(int16 val)
+{
+ uint16 buf;
+
+ buf = htons((uint16) val);
+ CopySendData(&buf, sizeof(buf));
+}
+
+/*
+ * CopyGetInt16 reads an int16 that appears in network byte order
+ */
+static int16
+CopyGetInt16(void)
+{
+ uint16 buf;
+
+ CopyGetData(&buf, sizeof(buf));
+ return (int16) ntohs(buf);
+}
+
/*
* DoCopy executes the SQL COPY statement.
@@ -802,7 +860,6 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
FmgrInfo *out_functions;
Oid *elements;
bool *isvarlena;
- int16 fld_size;
char *string;
Snapshot mySnapshot;
List *cur;
@@ -817,7 +874,6 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
/*
* Get info about the columns we need to process.
*
- * For binary copy we really only need isvarlena, but compute it all...
* +1's here are to avoid palloc(0) in a zero-column table.
*/
out_functions = (FmgrInfo *) palloc((num_phys_attrs + 1) * sizeof(FmgrInfo));
@@ -828,12 +884,15 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
int attnum = lfirsti(cur);
Oid out_func_oid;
- getTypeOutputInfo(attr[attnum - 1]->atttypid,
- &out_func_oid, &elements[attnum - 1],
- &isvarlena[attnum - 1]);
+ if (binary)
+ getTypeBinaryOutputInfo(attr[attnum - 1]->atttypid,
+ &out_func_oid, &elements[attnum - 1],
+ &isvarlena[attnum - 1]);
+ else
+ getTypeOutputInfo(attr[attnum - 1]->atttypid,
+ &out_func_oid, &elements[attnum - 1],
+ &isvarlena[attnum - 1]);
fmgr_info(out_func_oid, &out_functions[attnum - 1]);
- if (binary && attr[attnum - 1]->attlen == -2)
- elog(ERROR, "COPY BINARY: cstring not supported");
}
/*
@@ -854,18 +913,15 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
int32 tmp;
/* Signature */
- CopySendData((char *) BinarySignature, 12);
- /* Integer layout field */
- tmp = 0x01020304;
- CopySendData(&tmp, sizeof(int32));
+ CopySendData((char *) BinarySignature, 11);
/* Flags field */
tmp = 0;
if (oids)
tmp |= (1 << 16);
- CopySendData(&tmp, sizeof(int32));
+ CopySendInt32(tmp);
/* No header extension */
tmp = 0;
- CopySendData(&tmp, sizeof(int32));
+ CopySendInt32(tmp);
}
mySnapshot = CopyQuerySnapshot();
@@ -884,17 +940,15 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
if (binary)
{
/* Binary per-tuple header */
- int16 fld_count = attr_count;
-
- CopySendData(&fld_count, sizeof(int16));
- /* Send OID if wanted --- note fld_count doesn't include it */
+ CopySendInt16(attr_count);
+ /* Send OID if wanted --- note attr_count doesn't include it */
if (oids)
{
Oid oid = HeapTupleGetOid(tuple);
- fld_size = sizeof(Oid);
- CopySendData(&fld_size, sizeof(int16));
- CopySendData(&oid, sizeof(Oid));
+ /* Hack --- assume Oid is same size as int32 */
+ CopySendInt32(sizeof(int32));
+ CopySendInt32(oid);
}
}
else
@@ -927,14 +981,9 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
if (isnull)
{
if (!binary)
- {
CopySendString(null_print); /* null indicator */
- }
else
- {
- fld_size = 0; /* null marker */
- CopySendData(&fld_size, sizeof(int16));
- }
+ CopySendInt32(-1); /* null marker */
}
else
{
@@ -948,40 +997,15 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
}
else
{
- fld_size = attr[attnum - 1]->attlen;
- CopySendData(&fld_size, sizeof(int16));
- if (isvarlena[attnum - 1])
- {
- /* varlena */
- Assert(fld_size == -1);
-
- /* If we have a toasted datum, detoast it */
- value = PointerGetDatum(PG_DETOAST_DATUM(value));
-
- CopySendData(DatumGetPointer(value),
- VARSIZE(value));
- }
- else if (!attr[attnum - 1]->attbyval)
- {
- /* fixed-length pass-by-reference */
- Assert(fld_size > 0);
- CopySendData(DatumGetPointer(value),
- fld_size);
- }
- else
- {
- /* pass-by-value */
- Datum datumBuf;
-
- /*
- * We need this horsing around because we don't
- * know how shorter data values are aligned within
- * a Datum.
- */
- store_att_byval(&datumBuf, value, fld_size);
- CopySendData(&datumBuf,
- fld_size);
- }
+ bytea *outputbytes;
+
+ outputbytes = DatumGetByteaP(FunctionCall2(&out_functions[attnum - 1],
+ value,
+ ObjectIdGetDatum(elements[attnum - 1])));
+ /* We assume the result will not have been toasted */
+ CopySendInt32(VARSIZE(outputbytes) - VARHDRSZ);
+ CopySendData(VARDATA(outputbytes),
+ VARSIZE(outputbytes) - VARHDRSZ);
}
}
}
@@ -996,9 +1020,7 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
if (binary)
{
/* Generate trailer for a binary copy */
- int16 fld_count = -1;
-
- CopySendData(&fld_count, sizeof(int16));
+ CopySendInt16(-1);
}
MemoryContextDelete(mycontext);
@@ -1033,7 +1055,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
attr_count,
num_defaults;
FmgrInfo *in_functions;
+ FmgrInfo oid_in_function;
Oid *elements;
+ Oid oid_in_element;
ExprState **constraintexprs;
bool hasConstraints = false;
int i;
@@ -1042,6 +1066,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
Datum *values;
char *nulls;
bool done = false;
+ bool isnull;
ResultRelInfo *resultRelInfo;
EState *estate = CreateExecutorState(); /* for ExecConstraints() */
TupleTable tupleTable;
@@ -1086,7 +1111,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
* Pick up the required catalog information for each attribute in the
* relation, including the input function, the element type (to pass
* to the input function), and info about defaults and constraints.
- * (We don't actually use the input function if it's a binary copy.)
+ * (Which input function we use depends on text/binary format choice.)
* +1's here are to avoid palloc(0) in a zero-column table.
*/
in_functions = (FmgrInfo *) palloc((num_phys_attrs + 1) * sizeof(FmgrInfo));
@@ -1101,21 +1126,19 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
if (attr[i]->attisdropped)
continue;
- /* Fetch the input function */
- in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
+ /* Fetch the input function and typelem info */
+ if (binary)
+ getTypeBinaryInputInfo(attr[i]->atttypid,
+ &in_func_oid, &elements[i]);
+ else
+ getTypeInputInfo(attr[i]->atttypid,
+ &in_func_oid, &elements[i]);
fmgr_info(in_func_oid, &in_functions[i]);
- elements[i] = GetTypeElement(attr[i]->atttypid);
/* Get default info if needed */
- if (intMember(i + 1, attnumlist))
- {
- /* attribute is to be copied */
- if (binary && attr[i]->attlen == -2)
- elog(ERROR, "COPY BINARY: cstring not supported");
- }
- else
+ if (!intMember(i + 1, attnumlist))
{
- /* attribute is NOT to be copied */
+ /* attribute is NOT to be copied from input */
/* use default value if one exists */
Node *defexpr = build_column_default(rel, i + 1);
@@ -1174,19 +1197,15 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
else
{
/* Read and verify binary header */
- char readSig[12];
+ char readSig[11];
int32 tmp;
/* Signature */
- CopyGetData(readSig, 12);
- if (CopyGetEof() || memcmp(readSig, BinarySignature, 12) != 0)
+ CopyGetData(readSig, 11);
+ if (CopyGetEof() || memcmp(readSig, BinarySignature, 11) != 0)
elog(ERROR, "COPY BINARY: file signature not recognized");
- /* Integer layout field */
- CopyGetData(&tmp, sizeof(int32));
- if (CopyGetEof() || tmp != 0x01020304)
- elog(ERROR, "COPY BINARY: incompatible integer layout");
/* Flags field */
- CopyGetData(&tmp, sizeof(int32));
+ tmp = CopyGetInt32();
if (CopyGetEof())
elog(ERROR, "COPY BINARY: bogus file header (missing flags)");
file_has_oids = (tmp & (1 << 16)) != 0;
@@ -1194,7 +1213,7 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
if ((tmp >> 16) != 0)
elog(ERROR, "COPY BINARY: unrecognized critical flags in header");
/* Header extension length */
- CopyGetData(&tmp, sizeof(int32));
+ tmp = CopyGetInt32();
if (CopyGetEof() || tmp < 0)
elog(ERROR, "COPY BINARY: bogus file header (missing length)");
/* Skip extension header, if present */
@@ -1206,6 +1225,13 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
}
}
+ if (file_has_oids && binary)
+ {
+ getTypeBinaryInputInfo(OIDOID,
+ &in_func_oid, &oid_in_element);
+ fmgr_info(in_func_oid, &oid_in_function);
+ }
+
values = (Datum *) palloc((num_phys_attrs + 1) * sizeof(Datum));
nulls = (char *) palloc((num_phys_attrs + 1) * sizeof(char));
@@ -1351,10 +1377,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
else
{
/* binary */
- int16 fld_count,
- fld_size;
+ int16 fld_count;
- CopyGetData(&fld_count, sizeof(int16));
+ fld_count = CopyGetInt16();
if (CopyGetEof() || fld_count == -1)
{
done = true;
@@ -1367,16 +1392,12 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
if (file_has_oids)
{
- CopyGetData(&fld_size, sizeof(int16));
- if (CopyGetEof())
- elog(ERROR, "COPY BINARY: unexpected EOF");
- if (fld_size != (int16) sizeof(Oid))
- elog(ERROR, "COPY BINARY: sizeof(Oid) is %d, expected %d",
- (int) fld_size, (int) sizeof(Oid));
- CopyGetData(&loaded_oid, sizeof(Oid));
- if (CopyGetEof())
- elog(ERROR, "COPY BINARY: unexpected EOF");
- if (loaded_oid == InvalidOid)
+ loaded_oid =
+ DatumGetObjectId(CopyReadBinaryAttribute(0,
+ &oid_in_function,
+ oid_in_element,
+ &isnull));
+ if (isnull || loaded_oid == InvalidOid)
elog(ERROR, "COPY BINARY: Invalid Oid");
}
@@ -1387,63 +1408,11 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
int m = attnum - 1;
i++;
-
- CopyGetData(&fld_size, sizeof(int16));
- if (CopyGetEof())
- elog(ERROR, "COPY BINARY: unexpected EOF");
- if (fld_size == 0)
- continue; /* it's NULL; nulls[attnum-1] already set */
- if (fld_size != attr[m]->attlen)
- elog(ERROR, "COPY BINARY: sizeof(field %d) is %d, expected %d",
- i, (int) fld_size, (int) attr[m]->attlen);
- if (fld_size == -1)
- {
- /* varlena field */
- int32 varlena_size;
- Pointer varlena_ptr;
-
- CopyGetData(&varlena_size, sizeof(int32));
- if (CopyGetEof())
- elog(ERROR, "COPY BINARY: unexpected EOF");
- if (varlena_size < (int32) sizeof(int32))
- elog(ERROR, "COPY BINARY: bogus varlena length");
- varlena_ptr = (Pointer) palloc(varlena_size);
- VARATT_SIZEP(varlena_ptr) = varlena_size;
- CopyGetData(VARDATA(varlena_ptr),
- varlena_size - sizeof(int32));
- if (CopyGetEof())
- elog(ERROR, "COPY BINARY: unexpected EOF");
- values[m] = PointerGetDatum(varlena_ptr);
- }
- else if (!attr[m]->attbyval)
- {
- /* fixed-length pass-by-reference */
- Pointer refval_ptr;
-
- Assert(fld_size > 0);
- refval_ptr = (Pointer) palloc(fld_size);
- CopyGetData(refval_ptr, fld_size);
- if (CopyGetEof())
- elog(ERROR, "COPY BINARY: unexpected EOF");
- values[m] = PointerGetDatum(refval_ptr);
- }
- else
- {
- /* pass-by-value */
- Datum datumBuf;
-
- /*
- * We need this horsing around because we don't know
- * how shorter data values are aligned within a Datum.
- */
- Assert(fld_size > 0 && fld_size <= sizeof(Datum));
- CopyGetData(&datumBuf, fld_size);
- if (CopyGetEof())
- elog(ERROR, "COPY BINARY: unexpected EOF");
- values[m] = fetch_att(&datumBuf, true, fld_size);
- }
-
- nulls[m] = ' ';
+ values[m] = CopyReadBinaryAttribute(i,
+ &in_functions[m],
+ elements[m],
+ &isnull);
+ nulls[m] = isnull ? 'n' : ' ';
}
}
@@ -1454,8 +1423,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
*/
for (i = 0; i < num_defaults; i++)
{
- bool isnull;
-
values[defmap[i]] = ExecEvalExpr(defexprs[i], econtext,
&isnull, NULL);
if (!isnull)
@@ -1472,7 +1439,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
for (i = 0; i < num_phys_attrs; i++)
{
ExprState *exprstate = constraintexprs[i];
- bool isnull;
if (exprstate == NULL)
continue; /* no constraint for this attr */
@@ -1577,38 +1543,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
}
-static Oid
-GetInputFunction(Oid type)
-{
- HeapTuple typeTuple;
- Oid result;
-
- typeTuple = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(type),
- 0, 0, 0);
- if (!HeapTupleIsValid(typeTuple))
- elog(ERROR, "GetInputFunction: Cache lookup of type %u failed", type);
- result = ((Form_pg_type) GETSTRUCT(typeTuple))->typinput;
- ReleaseSysCache(typeTuple);
- return result;
-}
-
-static Oid
-GetTypeElement(Oid type)
-{
- HeapTuple typeTuple;
- Oid result;
-
- typeTuple = SearchSysCache(TYPEOID,
- ObjectIdGetDatum(type),
- 0, 0, 0);
- if (!HeapTupleIsValid(typeTuple))
- elog(ERROR, "GetTypeElement: Cache lookup of type %u failed", type);
- result = ((Form_pg_type) GETSTRUCT(typeTuple))->typelem;
- ReleaseSysCache(typeTuple);
- return result;
-}
-
/*
* Read the value of a single attribute.
*
@@ -1624,7 +1558,6 @@ GetTypeElement(Oid type)
*
* delim is the column delimiter string.
*/
-
static char *
CopyReadAttribute(const char *delim, CopyReadResult *result)
{
@@ -1848,6 +1781,57 @@ copy_eof:
return attribute_buf.data;
}
+/*
+ * Read a binary attribute
+ */
+static Datum
+CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo, Oid typelem,
+ bool *isnull)
+{
+ int32 fld_size;
+ Datum result;
+
+ fld_size = CopyGetInt32();
+ if (CopyGetEof())
+ elog(ERROR, "COPY BINARY: unexpected EOF");
+ if (fld_size == -1)
+ {
+ *isnull = true;
+ return (Datum) 0;
+ }
+ if (fld_size < 0)
+ elog(ERROR, "COPY BINARY: bogus size for field %d", column_no);
+
+ /* reset attribute_buf to empty, and load raw data in it */
+ attribute_buf.len = 0;
+ attribute_buf.data[0] = '\0';
+ attribute_buf.cursor = 0;
+
+ enlargeStringInfo(&attribute_buf, fld_size);
+
+ CopyGetData(attribute_buf.data, fld_size);
+ if (CopyGetEof())
+ elog(ERROR, "COPY BINARY: unexpected EOF");
+
+ attribute_buf.len = fld_size;
+ attribute_buf.data[fld_size] = '\0';
+
+ /* Call the column type's binary input converter */
+ result = FunctionCall2(flinfo,
+ PointerGetDatum(&attribute_buf),
+ ObjectIdGetDatum(typelem));
+
+ /* Trouble if it didn't eat the whole buffer */
+ if (attribute_buf.cursor != attribute_buf.len)
+ elog(ERROR, "Improper binary format in field %d", column_no);
+
+ *isnull = false;
+ return result;
+}
+
+/*
+ * Send text representation of one attribute, with conversion and escaping
+ */
static void
CopyAttributeOut(char *server_string, char *delim)
{
diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c
index 65fb49f48a5..0ea055b5222 100644
--- a/src/backend/libpq/pqformat.c
+++ b/src/backend/libpq/pqformat.c
@@ -24,7 +24,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Header: /cvsroot/pgsql/src/backend/libpq/pqformat.c,v 1.30 2003/05/09 15:44:40 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/libpq/pqformat.c,v 1.31 2003/05/09 21:19:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -35,6 +35,8 @@
* pq_sendbyte - append a raw byte to a StringInfo buffer
* pq_sendint - append a binary integer to a StringInfo buffer
* pq_sendint64 - append a binary 8-byte int to a StringInfo buffer
+ * pq_sendfloat4 - append a float4 to a StringInfo buffer
+ * pq_sendfloat8 - append a float8 to a StringInfo buffer
* pq_sendbytes - append raw data to a StringInfo buffer
* pq_sendcountedtext - append a counted text string (with character set conversion)
* pq_sendtext - append a text string (with conversion)
@@ -56,6 +58,8 @@
* pq_getmsgbyte - get a raw byte from a message buffer
* pq_getmsgint - get a binary integer from a message buffer
* pq_getmsgint64 - get a binary 8-byte int from a message buffer
+ * pq_getmsgfloat4 - get a float4 from a message buffer
+ * pq_getmsgfloat8 - get a float8 from a message buffer
* pq_getmsgbytes - get raw data from a message buffer
* pq_copymsgbytes - copy raw data from a message buffer
* pq_getmsgtext - get a counted text string (with conversion)
@@ -262,6 +266,82 @@ pq_sendint64(StringInfo buf, int64 i)
}
/* --------------------------------
+ * pq_sendfloat4 - append a float4 to a StringInfo buffer
+ *
+ * The point of this routine is to localize knowledge of the external binary
+ * representation of float4, which is a component of several datatypes.
+ *
+ * We currently assume that float4 should be byte-swapped in the same way
+ * as int4. This rule is not perfect but it gives us portability across
+ * most IEEE-float-using architectures.
+ * --------------------------------
+ */
+void
+pq_sendfloat4(StringInfo buf, float4 f)
+{
+ union
+ {
+ float4 f;
+ uint32 i;
+ } swap;
+
+ swap.f = f;
+ swap.i = htonl(swap.i);
+
+ appendBinaryStringInfo(buf, (char *) &swap.i, 4);
+}
+
+/* --------------------------------
+ * pq_sendfloat8 - append a float8 to a StringInfo buffer
+ *
+ * The point of this routine is to localize knowledge of the external binary
+ * representation of float8, which is a component of several datatypes.
+ *
+ * We currently assume that float8 should be byte-swapped in the same way
+ * as int8. This rule is not perfect but it gives us portability across
+ * most IEEE-float-using architectures.
+ * --------------------------------
+ */
+void
+pq_sendfloat8(StringInfo buf, float8 f)
+{
+#ifdef INT64_IS_BUSTED
+ union
+ {
+ float8 f;
+ uint32 h[2];
+ } swap;
+
+ swap.f = f;
+ swap.h[0] = htonl(swap.h[0]);
+ swap.h[1] = htonl(swap.h[1]);
+
+ /* Have to figure out endianness by testing... */
+ if (((uint32) 1) == htonl((uint32) 1))
+ {
+ /* machine seems to be big-endian, send h[0] first */
+ appendBinaryStringInfo(buf, (char *) &swap.h[0], 4);
+ appendBinaryStringInfo(buf, (char *) &swap.h[1], 4);
+ }
+ else
+ {
+ /* machine seems to be little-endian, send h[1] first */
+ appendBinaryStringInfo(buf, (char *) &swap.h[1], 4);
+ appendBinaryStringInfo(buf, (char *) &swap.h[0], 4);
+ }
+#else
+ union
+ {
+ float8 f;
+ int64 i;
+ } swap;
+
+ swap.f = f;
+ pq_sendint64(buf, swap.i);
+#endif
+}
+
+/* --------------------------------
* pq_endmessage - send the completed message to the frontend
*
* The data buffer is pfree()d, but if the StringInfo was allocated with
@@ -433,6 +513,67 @@ pq_getmsgint64(StringInfo msg)
}
/* --------------------------------
+ * pq_getmsgfloat4 - get a float4 from a message buffer
+ *
+ * See notes for pq_sendfloat4.
+ * --------------------------------
+ */
+float4
+pq_getmsgfloat4(StringInfo msg)
+{
+ union
+ {
+ float4 f;
+ uint32 i;
+ } swap;
+
+ swap.i = pq_getmsgint(msg, 4);
+ return swap.f;
+}
+
+/* --------------------------------
+ * pq_getmsgfloat8 - get a float8 from a message buffer
+ *
+ * See notes for pq_sendfloat8.
+ * --------------------------------
+ */
+float8
+pq_getmsgfloat8(StringInfo msg)
+{
+#ifdef INT64_IS_BUSTED
+ union
+ {
+ float8 f;
+ uint32 h[2];
+ } swap;
+
+ /* Have to figure out endianness by testing... */
+ if (((uint32) 1) == htonl((uint32) 1))
+ {
+ /* machine seems to be big-endian, receive h[0] first */
+ swap.h[0] = pq_getmsgint(msg, 4);
+ swap.h[1] = pq_getmsgint(msg, 4);
+ }
+ else
+ {
+ /* machine seems to be little-endian, receive h[1] first */
+ swap.h[1] = pq_getmsgint(msg, 4);
+ swap.h[0] = pq_getmsgint(msg, 4);
+ }
+ return swap.f;
+#else
+ union
+ {
+ float8 f;
+ int64 i;
+ } swap;
+
+ swap.i = pq_getmsgint64(msg);
+ return swap.f;
+#endif
+}
+
+/* --------------------------------
* pq_getmsgbytes - get raw data from a message buffer
*
* Returns a pointer directly into the message buffer; note this
diff --git a/src/backend/utils/adt/float.c b/src/backend/utils/adt/float.c
index 4f770a2e975..e954e7e9493 100644
--- a/src/backend/utils/adt/float.c
+++ b/src/backend/utils/adt/float.c
@@ -8,16 +8,18 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.86 2003/05/09 16:31:24 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.87 2003/05/09 21:19:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*----------
* OLD COMMENTS
* Basic float4 ops:
- * float4in, float4out, float4abs, float4um, float4up
+ * float4in, float4out, float4recv, float4send
+ * float4abs, float4um, float4up
* Basic float8 ops:
- * float8in, float8out, float8abs, float8um, float8up
+ * float8in, float8out, float8recv, float8send
+ * float8abs, float8um, float8up
* Arithmetic operators:
* float4pl, float4mi, float4mul, float4div
* float8pl, float8mi, float8mul, float8div
@@ -63,6 +65,7 @@
#include "catalog/pg_type.h"
#include "fmgr.h"
+#include "libpq/pqformat.h"
#include "utils/array.h"
#include "utils/builtins.h"
@@ -243,6 +246,31 @@ float4out(PG_FUNCTION_ARGS)
}
/*
+ * float4recv - converts external binary format to float4
+ */
+Datum
+float4recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+
+ PG_RETURN_FLOAT4(pq_getmsgfloat4(buf));
+}
+
+/*
+ * float4send - converts float4 to binary format
+ */
+Datum
+float4send(PG_FUNCTION_ARGS)
+{
+ float4 num = PG_GETARG_FLOAT4(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendfloat4(&buf, num);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+/*
* float8in - converts "num" to float8
* restricted syntax:
* {<sp>} [+|-] {digit} [.{digit}] [<exp>]
@@ -280,7 +308,6 @@ float8in(PG_FUNCTION_ARGS)
PG_RETURN_FLOAT8(val);
}
-
/*
* float8out - converts float8 number to a string
* using a standard output format
@@ -310,6 +337,32 @@ float8out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(ascii);
}
+/*
+ * float8recv - converts external binary format to float8
+ */
+Datum
+float8recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+
+ PG_RETURN_FLOAT8(pq_getmsgfloat8(buf));
+}
+
+/*
+ * float8send - converts float8 to binary format
+ */
+Datum
+float8send(PG_FUNCTION_ARGS)
+{
+ float8 num = PG_GETARG_FLOAT8(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendfloat8(&buf, num);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+
/* ========== PUBLIC ROUTINES ========== */
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index d8d1f7c3afe..956bd1753f6 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.75 2003/03/11 21:01:33 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/geo_ops.c,v 1.76 2003/05/09 21:19:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -19,11 +19,11 @@
#include <float.h>
#include <ctype.h>
+#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/geo_decls.h"
#ifndef M_PI
-/* from my RH5.2 gcc math.h file - thomas 2000-04-03 */
#define M_PI 3.14159265358979323846
#endif
@@ -1589,6 +1589,36 @@ point_out(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(path_encode(-1, 1, pt));
}
+/*
+ * point_recv - converts external binary format to point
+ */
+Datum
+point_recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ Point *point;
+
+ point = (Point *) palloc(sizeof(Point));
+ point->x = pq_getmsgfloat8(buf);
+ point->y = pq_getmsgfloat8(buf);
+ PG_RETURN_POINT_P(point);
+}
+
+/*
+ * point_send - converts point to binary format
+ */
+Datum
+point_send(PG_FUNCTION_ARGS)
+{
+ Point *pt = PG_GETARG_POINT_P(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendfloat8(&buf, pt->x);
+ pq_sendfloat8(&buf, pt->y);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
static Point *
point_construct(double x, double y)
diff --git a/src/backend/utils/adt/name.c b/src/backend/utils/adt/name.c
index 607f7876a85..b7a56cb1cb1 100644
--- a/src/backend/utils/adt/name.c
+++ b/src/backend/utils/adt/name.c
@@ -2,8 +2,10 @@
*
* name.c
* Functions for the built-in type "name".
+ *
* name replaces char16 and is carefully implemented so that it
- * is a string of length NAMEDATALEN. DO NOT use hard-coded constants anywhere
+ * is a string of physical length NAMEDATALEN.
+ * DO NOT use hard-coded constants anywhere
* always use NAMEDATALEN as the symbolic constant! - jolly 8/21/95
*
*
@@ -12,7 +14,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.44 2003/04/27 23:22:13 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/name.c,v 1.45 2003/05/09 21:19:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -20,11 +22,13 @@
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
+#include "libpq/pqformat.h"
+#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
-#include "mb/pg_wchar.h"
+
/*****************************************************************************
* USER I/O ROUTINES (none) *
@@ -53,9 +57,7 @@ namein(PG_FUNCTION_ARGS)
len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
- result = (NameData *) palloc(NAMEDATALEN);
- /* always keep it null-padded */
- memset(result, 0, NAMEDATALEN);
+ result = (NameData *) palloc0(NAMEDATALEN);
memcpy(NameStr(*result), s, len);
PG_RETURN_NAME(result);
@@ -72,6 +74,40 @@ nameout(PG_FUNCTION_ARGS)
PG_RETURN_CSTRING(pstrdup(NameStr(*s)));
}
+/*
+ * namerecv - converts external binary format to name
+ */
+Datum
+namerecv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ Name result;
+ char *str;
+ int nbytes;
+
+ str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
+ if (nbytes >= NAMEDATALEN)
+ elog(ERROR, "namerecv: input name too long");
+ result = (NameData *) palloc0(NAMEDATALEN);
+ memcpy(result, str, nbytes);
+ pfree(str);
+ PG_RETURN_NAME(result);
+}
+
+/*
+ * namesend - converts name to binary format
+ */
+Datum
+namesend(PG_FUNCTION_ARGS)
+{
+ Name s = PG_GETARG_NAME(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendtext(&buf, NameStr(*s), strlen(NameStr(*s)));
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
/*****************************************************************************
* PUBLIC ROUTINES *
@@ -283,24 +319,3 @@ current_schemas(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(array);
}
-
-
-/*****************************************************************************
- * PRIVATE ROUTINES *
- *****************************************************************************/
-
-#ifdef NOT_USED
-uint32
-NameComputeLength(Name name)
-{
- char *charP;
- int length;
-
- for (length = 0, charP = NameStr(*name);
- length < NAMEDATALEN && *charP != '\0';
- length++, charP++)
- ;
- return (uint32) length;
-}
-
-#endif
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 8046e5c4c68..e205448ec6d 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catversion.h,v 1.188 2003/05/09 15:44:40 tgl Exp $
+ * $Id: catversion.h,v 1.189 2003/05/09 21:19:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -53,6 +53,6 @@
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 200305091
+#define CATALOG_VERSION_NO 200305092
#endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 0d801214f58..bc186f2eed9 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_proc.h,v 1.295 2003/05/09 15:44:40 tgl Exp $
+ * $Id: pg_proc.h,v 1.296 2003/05/09 21:19:49 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@@ -3197,6 +3197,22 @@ DATA(insert OID = 2420 ( oidvectorrecv PGNSP PGUID 12 f f t f i 1 30 "2281"
DESCR("I/O");
DATA(insert OID = 2421 ( oidvectorsend PGNSP PGUID 12 f f t f i 1 17 "30" oidvectorsend - _null_ ));
DESCR("I/O");
+DATA(insert OID = 2422 ( namerecv PGNSP PGUID 12 f f t f s 1 19 "2281" namerecv - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2423 ( namesend PGNSP PGUID 12 f f t f s 1 17 "19" namesend - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2424 ( float4recv PGNSP PGUID 12 f f t f i 1 700 "2281" float4recv - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2425 ( float4send PGNSP PGUID 12 f f t f i 1 17 "700" float4send - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2426 ( float8recv PGNSP PGUID 12 f f t f i 1 701 "2281" float8recv - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2427 ( float8send PGNSP PGUID 12 f f t f i 1 17 "701" float8send - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2428 ( point_recv PGNSP PGUID 12 f f t f i 1 600 "2281" point_recv - _null_ ));
+DESCR("I/O");
+DATA(insert OID = 2429 ( point_send PGNSP PGUID 12 f f t f i 1 17 "600" point_send - _null_ ));
+DESCR("I/O");
/*
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 3091578b609..ea504bd7937 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pg_type.h,v 1.142 2003/05/09 15:44:41 tgl Exp $
+ * $Id: pg_type.h,v 1.143 2003/05/09 21:19:50 tgl Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
@@ -250,8 +250,8 @@ DATA(insert OID = 18 ( char PGNSP PGUID 1 t b t \054 0 0 charin charout - -
DESCR("single character");
#define CHAROID 18
-DATA(insert OID = 19 ( name PGNSP PGUID NAMEDATALEN f b t \054 0 18 namein nameout - - i p f 0 -1 0 _null_ _null_ ));
-DESCR("31-character type for storing system identifiers");
+DATA(insert OID = 19 ( name PGNSP PGUID NAMEDATALEN f b t \054 0 18 namein nameout namerecv namesend i p f 0 -1 0 _null_ _null_ ));
+DESCR("63-character type for storing system identifiers");
#define NAMEOID 19
DATA(insert OID = 20 ( int8 PGNSP PGUID 8 f b t \054 0 0 int8in int8out int8recv int8send d p f 0 -1 0 _null_ _null_ ));
@@ -323,7 +323,7 @@ DESCR("storage manager");
/* OIDS 500 - 599 */
/* OIDS 600 - 699 */
-DATA(insert OID = 600 ( point PGNSP PGUID 16 f b t \054 0 701 point_in point_out - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 600 ( point PGNSP PGUID 16 f b t \054 0 701 point_in point_out point_recv point_send d p f 0 -1 0 _null_ _null_ ));
DESCR("geometric point '(x, y)'");
#define POINTOID 600
DATA(insert OID = 601 ( lseg PGNSP PGUID 32 f b t \054 0 600 lseg_in lseg_out - - d p f 0 -1 0 _null_ _null_ ));
@@ -347,10 +347,10 @@ DESCR("");
/* OIDS 700 - 799 */
-DATA(insert OID = 700 ( float4 PGNSP PGUID 4 f b t \054 0 0 float4in float4out - - i p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 700 ( float4 PGNSP PGUID 4 f b t \054 0 0 float4in float4out float4recv float4send i p f 0 -1 0 _null_ _null_ ));
DESCR("single-precision floating point number, 4-byte storage");
#define FLOAT4OID 700
-DATA(insert OID = 701 ( float8 PGNSP PGUID 8 f b t \054 0 0 float8in float8out - - d p f 0 -1 0 _null_ _null_ ));
+DATA(insert OID = 701 ( float8 PGNSP PGUID 8 f b t \054 0 0 float8in float8out float8recv float8send d p f 0 -1 0 _null_ _null_ ));
DESCR("double-precision floating point number, 8-byte storage");
#define FLOAT8OID 701
DATA(insert OID = 702 ( abstime PGNSP PGUID 4 t b t \054 0 0 nabstimein nabstimeout - - i p f 0 -1 0 _null_ _null_ ));
diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h
index bbeff288c4f..2102960e884 100644
--- a/src/include/libpq/pqformat.h
+++ b/src/include/libpq/pqformat.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: pqformat.h,v 1.17 2003/05/09 15:44:42 tgl Exp $
+ * $Id: pqformat.h,v 1.18 2003/05/09 21:19:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -24,6 +24,8 @@ extern void pq_sendtext(StringInfo buf, const char *str, int slen);
extern void pq_sendstring(StringInfo buf, const char *str);
extern void pq_sendint(StringInfo buf, int i, int b);
extern void pq_sendint64(StringInfo buf, int64 i);
+extern void pq_sendfloat4(StringInfo buf, float4 f);
+extern void pq_sendfloat8(StringInfo buf, float8 f);
extern void pq_endmessage(StringInfo buf);
extern void pq_begintypsend(StringInfo buf);
@@ -35,6 +37,8 @@ extern void pq_putemptymessage(char msgtype);
extern int pq_getmsgbyte(StringInfo msg);
extern unsigned int pq_getmsgint(StringInfo msg, int b);
extern int64 pq_getmsgint64(StringInfo msg);
+extern float4 pq_getmsgfloat4(StringInfo msg);
+extern float8 pq_getmsgfloat8(StringInfo msg);
extern const char *pq_getmsgbytes(StringInfo msg, int datalen);
extern void pq_copymsgbytes(StringInfo msg, char *buf, int datalen);
extern char *pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes);
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index 15dfd11a1f5..85b34308eea 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: builtins.h,v 1.213 2003/05/09 15:44:42 tgl Exp $
+ * $Id: builtins.h,v 1.214 2003/05/09 21:19:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -181,6 +181,8 @@ extern Datum int2shr(PG_FUNCTION_ARGS);
/* name.c */
extern Datum namein(PG_FUNCTION_ARGS);
extern Datum nameout(PG_FUNCTION_ARGS);
+extern Datum namerecv(PG_FUNCTION_ARGS);
+extern Datum namesend(PG_FUNCTION_ARGS);
extern Datum nameeq(PG_FUNCTION_ARGS);
extern Datum namene(PG_FUNCTION_ARGS);
extern Datum namelt(PG_FUNCTION_ARGS);
@@ -222,8 +224,12 @@ extern int extra_float_digits;
extern Datum float4in(PG_FUNCTION_ARGS);
extern Datum float4out(PG_FUNCTION_ARGS);
+extern Datum float4recv(PG_FUNCTION_ARGS);
+extern Datum float4send(PG_FUNCTION_ARGS);
extern Datum float8in(PG_FUNCTION_ARGS);
extern Datum float8out(PG_FUNCTION_ARGS);
+extern Datum float8recv(PG_FUNCTION_ARGS);
+extern Datum float8send(PG_FUNCTION_ARGS);
extern Datum float4abs(PG_FUNCTION_ARGS);
extern Datum float4um(PG_FUNCTION_ARGS);
extern Datum float4up(PG_FUNCTION_ARGS);
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 0e299089775..91cbe10d350 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: geo_decls.h,v 1.38 2002/06/20 20:29:52 momjian Exp $
+ * $Id: geo_decls.h,v 1.39 2003/05/09 21:19:50 tgl Exp $
*
* NOTE
* These routines do *not* use the float types from adt/.
@@ -188,6 +188,8 @@ typedef struct
/* public point routines */
extern Datum point_in(PG_FUNCTION_ARGS);
extern Datum point_out(PG_FUNCTION_ARGS);
+extern Datum point_recv(PG_FUNCTION_ARGS);
+extern Datum point_send(PG_FUNCTION_ARGS);
extern Datum construct_point(PG_FUNCTION_ARGS);
extern Datum point_left(PG_FUNCTION_ARGS);
extern Datum point_right(PG_FUNCTION_ARGS);