mirror of
https://github.com/postgres/postgres.git
synced 2025-11-13 16:22:44 +03:00
Binary send/receive routines for a few basic datatypes --- enough for
testing purposes.
This commit is contained in:
@@ -15,10 +15,16 @@
|
||||
* pq_getmessage, and then parsed and converted from that using the routines
|
||||
* in this module.
|
||||
*
|
||||
* These same routines support reading and writing of external binary formats
|
||||
* (typsend/typreceive routines). The conversion routines for individual
|
||||
* data types are exactly the same, only initialization and completion
|
||||
* are different.
|
||||
*
|
||||
*
|
||||
* 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.29 2003/05/08 18:16:36 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/pqformat.c,v 1.30 2003/05/09 15:44:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -28,14 +34,20 @@
|
||||
* pq_beginmessage - initialize StringInfo buffer
|
||||
* 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_sendbytes - append raw data to a StringInfo buffer
|
||||
* pq_sendcountedtext - append a text string (with character set conversion)
|
||||
* pq_sendcountedtext - append a counted text string (with character set conversion)
|
||||
* pq_sendtext - append a text string (with conversion)
|
||||
* pq_sendstring - append a null-terminated text string (with conversion)
|
||||
* pq_endmessage - send the completed message to the frontend
|
||||
* Note: it is also possible to append data to the StringInfo buffer using
|
||||
* the regular StringInfo routines, but this is discouraged since required
|
||||
* character set conversion may not occur.
|
||||
*
|
||||
* typsend support (construct a bytea value containing external binary data):
|
||||
* pq_begintypsend - initialize StringInfo buffer
|
||||
* pq_endtypsend - return the completed string as a "bytea*"
|
||||
*
|
||||
* Special-case message output:
|
||||
* pq_puttextmessage - generate a character set-converted message in one step
|
||||
* pq_putemptymessage - convenience routine for message with empty body
|
||||
@@ -43,8 +55,10 @@
|
||||
* Message parsing after input:
|
||||
* 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_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)
|
||||
* pq_getmsgstring - get a null-terminated text string (with conversion)
|
||||
* pq_getmsgend - verify message fully consumed
|
||||
*/
|
||||
@@ -101,7 +115,7 @@ pq_sendbytes(StringInfo buf, const char *data, int datalen)
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_sendcountedtext - append a text string (with character set conversion)
|
||||
* pq_sendcountedtext - append a counted text string (with character set conversion)
|
||||
*
|
||||
* The data sent to the frontend by this routine is a 4-byte count field
|
||||
* followed by the string. The count includes itself or not, as per the
|
||||
@@ -132,6 +146,34 @@ pq_sendcountedtext(StringInfo buf, const char *str, int slen,
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_sendtext - append a text string (with conversion)
|
||||
*
|
||||
* The passed text string need not be null-terminated, and the data sent
|
||||
* to the frontend isn't either. Note that this is not actually useful
|
||||
* for direct frontend transmissions, since there'd be no way for the
|
||||
* frontend to determine the string length. But it is useful for binary
|
||||
* format conversions.
|
||||
* --------------------------------
|
||||
*/
|
||||
void
|
||||
pq_sendtext(StringInfo buf, const char *str, int slen)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = (char *) pg_server_to_client((unsigned char *) str, slen);
|
||||
if (p != str) /* actual conversion has been done? */
|
||||
{
|
||||
slen = strlen(p);
|
||||
appendBinaryStringInfo(buf, p, slen);
|
||||
pfree(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
appendBinaryStringInfo(buf, str, slen);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_sendstring - append a null-terminated text string (with conversion)
|
||||
*
|
||||
@@ -152,9 +194,11 @@ pq_sendstring(StringInfo buf, const char *str)
|
||||
slen = strlen(p);
|
||||
appendBinaryStringInfo(buf, p, slen + 1);
|
||||
pfree(p);
|
||||
return;
|
||||
}
|
||||
appendBinaryStringInfo(buf, str, slen + 1);
|
||||
else
|
||||
{
|
||||
appendBinaryStringInfo(buf, str, slen + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
@@ -188,6 +232,35 @@ pq_sendint(StringInfo buf, int i, int b)
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_sendint64 - append a binary 8-byte int to a StringInfo buffer
|
||||
*
|
||||
* It is tempting to merge this with pq_sendint, but we'd have to make the
|
||||
* argument int64 for all data widths --- that could be a big performance
|
||||
* hit on machines where int64 isn't efficient.
|
||||
* --------------------------------
|
||||
*/
|
||||
void
|
||||
pq_sendint64(StringInfo buf, int64 i)
|
||||
{
|
||||
uint32 n32;
|
||||
|
||||
/* High order half first, since we're doing MSB-first */
|
||||
#ifdef INT64_IS_BUSTED
|
||||
/* don't try a right shift of 32 on a 32-bit word */
|
||||
n32 = (i < 0) ? -1 : 0;
|
||||
#else
|
||||
n32 = (uint32) (i >> 32);
|
||||
#endif
|
||||
n32 = htonl(n32);
|
||||
appendBinaryStringInfo(buf, (char *) &n32, 4);
|
||||
|
||||
/* Now the low order half */
|
||||
n32 = (uint32) i;
|
||||
n32 = htonl(n32);
|
||||
appendBinaryStringInfo(buf, (char *) &n32, 4);
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_endmessage - send the completed message to the frontend
|
||||
*
|
||||
@@ -205,6 +278,44 @@ pq_endmessage(StringInfo buf)
|
||||
buf->data = NULL;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------
|
||||
* pq_begintypsend - initialize for constructing a bytea result
|
||||
* --------------------------------
|
||||
*/
|
||||
void
|
||||
pq_begintypsend(StringInfo buf)
|
||||
{
|
||||
initStringInfo(buf);
|
||||
/* Reserve four bytes for the bytea length word */
|
||||
appendStringInfoCharMacro(buf, '\0');
|
||||
appendStringInfoCharMacro(buf, '\0');
|
||||
appendStringInfoCharMacro(buf, '\0');
|
||||
appendStringInfoCharMacro(buf, '\0');
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_endtypsend - finish constructing a bytea result
|
||||
*
|
||||
* The data buffer is returned as the palloc'd bytea value. (We expect
|
||||
* that it will be suitably aligned for this because it has been palloc'd.)
|
||||
* We assume the StringInfoData is just a local variable in the caller and
|
||||
* need not be pfree'd.
|
||||
* --------------------------------
|
||||
*/
|
||||
bytea *
|
||||
pq_endtypsend(StringInfo buf)
|
||||
{
|
||||
bytea *result = (bytea *) buf->data;
|
||||
|
||||
/* Insert correct length into bytea length word */
|
||||
Assert(buf->len >= VARHDRSZ);
|
||||
VARATT_SIZEP(result) = buf->len;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------
|
||||
* pq_puttextmessage - generate a character set-converted message in one step
|
||||
*
|
||||
@@ -289,6 +400,38 @@ pq_getmsgint(StringInfo msg, int b)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_getmsgint64 - get a binary 8-byte int from a message buffer
|
||||
*
|
||||
* It is tempting to merge this with pq_getmsgint, but we'd have to make the
|
||||
* result int64 for all data widths --- that could be a big performance
|
||||
* hit on machines where int64 isn't efficient.
|
||||
* --------------------------------
|
||||
*/
|
||||
int64
|
||||
pq_getmsgint64(StringInfo msg)
|
||||
{
|
||||
int64 result;
|
||||
uint32 h32;
|
||||
uint32 l32;
|
||||
|
||||
pq_copymsgbytes(msg, (char *) &h32, 4);
|
||||
pq_copymsgbytes(msg, (char *) &l32, 4);
|
||||
h32 = ntohl(h32);
|
||||
l32 = ntohl(l32);
|
||||
|
||||
#ifdef INT64_IS_BUSTED
|
||||
/* just lose the high half */
|
||||
result = l32;
|
||||
#else
|
||||
result = h32;
|
||||
result <<= 32;
|
||||
result |= l32;
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_getmsgbytes - get raw data from a message buffer
|
||||
*
|
||||
@@ -323,6 +466,39 @@ pq_copymsgbytes(StringInfo msg, char *buf, int datalen)
|
||||
msg->cursor += datalen;
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_getmsgtext - get a counted text string (with conversion)
|
||||
*
|
||||
* Always returns a pointer to a freshly palloc'd result.
|
||||
* The result has a trailing null, *and* we return its strlen in *nbytes.
|
||||
* --------------------------------
|
||||
*/
|
||||
char *
|
||||
pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
|
||||
{
|
||||
char *str;
|
||||
char *p;
|
||||
|
||||
if (rawbytes < 0 || rawbytes > (msg->len - msg->cursor))
|
||||
elog(ERROR, "pq_getmsgtext: insufficient data left in message");
|
||||
str = &msg->data[msg->cursor];
|
||||
msg->cursor += rawbytes;
|
||||
|
||||
p = (char *) pg_client_to_server((unsigned char *) str, rawbytes);
|
||||
if (p != str) /* actual conversion has been done? */
|
||||
{
|
||||
*nbytes = strlen(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = (char *) palloc(rawbytes + 1);
|
||||
memcpy(p, str, rawbytes);
|
||||
p[rawbytes] = '\0';
|
||||
*nbytes = rawbytes;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_getmsgstring - get a null-terminated text string (with conversion)
|
||||
*
|
||||
|
||||
@@ -8,14 +8,16 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.53 2003/03/11 21:01:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.54 2003/05/09 15:44:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
/*
|
||||
* OLD COMMENTS
|
||||
* I/O routines:
|
||||
* int2in, int2out, int2vectorin, int2vectorout, int4in, int4out
|
||||
* int2in, int2out, int2recv, int2send
|
||||
* int4in, int4out, int4recv, int4send
|
||||
* int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
|
||||
* Conversion routines:
|
||||
* itoi, int2_text, int4_text
|
||||
* Boolean operators:
|
||||
@@ -32,6 +34,7 @@
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "libpq/pqformat.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
#ifndef SHRT_MAX
|
||||
@@ -69,6 +72,31 @@ int2out(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* int2recv - converts external binary format to int2
|
||||
*/
|
||||
Datum
|
||||
int2recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
|
||||
}
|
||||
|
||||
/*
|
||||
* int2send - converts int2 to binary format
|
||||
*/
|
||||
Datum
|
||||
int2send(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int16 arg1 = PG_GETARG_INT16(0);
|
||||
StringInfoData buf;
|
||||
|
||||
pq_begintypsend(&buf);
|
||||
pq_sendint(&buf, arg1, sizeof(int16));
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* int2vectorin - converts "num num ..." to internal form
|
||||
*
|
||||
@@ -131,6 +159,41 @@ int2vectorout(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* int2vectorrecv - converts external binary format to int2vector
|
||||
*/
|
||||
Datum
|
||||
int2vectorrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
int16 *result = (int16 *) palloc(sizeof(int16[INDEX_MAX_KEYS]));
|
||||
int slot;
|
||||
|
||||
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
|
||||
{
|
||||
result[slot] = (int16) pq_getmsgint(buf, sizeof(int16));
|
||||
}
|
||||
PG_RETURN_POINTER(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* int2vectorsend - converts int2vector to binary format
|
||||
*/
|
||||
Datum
|
||||
int2vectorsend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int16 *int2Array = (int16 *) PG_GETARG_POINTER(0);
|
||||
StringInfoData buf;
|
||||
int slot;
|
||||
|
||||
pq_begintypsend(&buf);
|
||||
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
|
||||
{
|
||||
pq_sendint(&buf, int2Array[slot], sizeof(int16));
|
||||
}
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't have a complete set of int2vector support routines,
|
||||
* but we need int2vectoreq for catcache indexing.
|
||||
@@ -173,6 +236,31 @@ int4out(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* int4recv - converts external binary format to int4
|
||||
*/
|
||||
Datum
|
||||
int4recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
|
||||
}
|
||||
|
||||
/*
|
||||
* int4send - converts int4 to binary format
|
||||
*/
|
||||
Datum
|
||||
int4send(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int32 arg1 = PG_GETARG_INT32(0);
|
||||
StringInfoData buf;
|
||||
|
||||
pq_begintypsend(&buf);
|
||||
pq_sendint(&buf, arg1, sizeof(int32));
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ===================
|
||||
|
||||
@@ -7,36 +7,21 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.43 2003/03/11 21:01:33 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.44 2003/05/09 15:44:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "libpq/pqformat.h"
|
||||
#include "utils/int8.h"
|
||||
|
||||
|
||||
#define MAXINT8LEN 25
|
||||
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX (0x7FFFFFFFL)
|
||||
#endif
|
||||
#ifndef INT_MIN
|
||||
#define INT_MIN (-INT_MAX-1)
|
||||
#endif
|
||||
#ifndef SHRT_MAX
|
||||
#define SHRT_MAX (0x7FFF)
|
||||
#endif
|
||||
#ifndef SHRT_MIN
|
||||
#define SHRT_MIN (-SHRT_MAX-1)
|
||||
#endif
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
**
|
||||
@@ -160,6 +145,31 @@ int8out(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* int8recv - converts external binary format to int8
|
||||
*/
|
||||
Datum
|
||||
int8recv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
PG_RETURN_INT64(pq_getmsgint64(buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* int8send - converts int8 to binary format
|
||||
*/
|
||||
Datum
|
||||
int8send(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int64 arg1 = PG_GETARG_INT64(0);
|
||||
StringInfoData buf;
|
||||
|
||||
pq_begintypsend(&buf);
|
||||
pq_sendint64(&buf, arg1);
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------
|
||||
* Relational operators for int8s, including cross-data-type comparisons.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.47 2002/06/20 20:29:38 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/oid.c,v 1.48 2003/05/09 15:44:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -18,8 +18,10 @@
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "libpq/pqformat.h"
|
||||
#include "utils/builtins.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* USER I/O ROUTINES *
|
||||
*****************************************************************************/
|
||||
@@ -108,6 +110,31 @@ oidout(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* oidrecv - converts external binary format to oid
|
||||
*/
|
||||
Datum
|
||||
oidrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
|
||||
PG_RETURN_OID((Oid) pq_getmsgint(buf, sizeof(Oid)));
|
||||
}
|
||||
|
||||
/*
|
||||
* oidsend - converts oid to binary format
|
||||
*/
|
||||
Datum
|
||||
oidsend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid arg1 = PG_GETARG_OID(0);
|
||||
StringInfoData buf;
|
||||
|
||||
pq_begintypsend(&buf);
|
||||
pq_sendint(&buf, arg1, sizeof(Oid));
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* oidvectorin - converts "num num ..." to internal form
|
||||
@@ -119,11 +146,9 @@ Datum
|
||||
oidvectorin(PG_FUNCTION_ARGS)
|
||||
{
|
||||
char *oidString = PG_GETARG_CSTRING(0);
|
||||
Oid *result;
|
||||
Oid *result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
|
||||
int slot;
|
||||
|
||||
result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
|
||||
|
||||
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
|
||||
{
|
||||
while (*oidString && isspace((unsigned char) *oidString))
|
||||
@@ -173,6 +198,42 @@ oidvectorout(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* oidvectorrecv - converts external binary format to oidvector
|
||||
*/
|
||||
Datum
|
||||
oidvectorrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
Oid *result = (Oid *) palloc(sizeof(Oid[INDEX_MAX_KEYS]));
|
||||
int slot;
|
||||
|
||||
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
|
||||
{
|
||||
result[slot] = (Oid) pq_getmsgint(buf, sizeof(Oid));
|
||||
}
|
||||
PG_RETURN_POINTER(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* oidvectorsend - converts oidvector to binary format
|
||||
*/
|
||||
Datum
|
||||
oidvectorsend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Oid *oidArray = (Oid *) PG_GETARG_POINTER(0);
|
||||
StringInfoData buf;
|
||||
int slot;
|
||||
|
||||
pq_begintypsend(&buf);
|
||||
for (slot = 0; slot < INDEX_MAX_KEYS; slot++)
|
||||
{
|
||||
pq_sendint(&buf, oidArray[slot], sizeof(Oid));
|
||||
}
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* PUBLIC ROUTINES *
|
||||
*****************************************************************************/
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.96 2003/04/24 21:16:43 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.97 2003/05/09 15:44:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -20,16 +20,20 @@
|
||||
#include "miscadmin.h"
|
||||
#include "access/tuptoaster.h"
|
||||
#include "lib/stringinfo.h"
|
||||
#include "libpq/crypt.h"
|
||||
#include "libpq/pqformat.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/pg_locale.h"
|
||||
|
||||
extern bool md5_hash(const void *buff, size_t len, char *hexsum);
|
||||
|
||||
typedef struct varlena unknown;
|
||||
|
||||
#define DatumGetUnknownP(X) ((unknown *) PG_DETOAST_DATUM(X))
|
||||
#define DatumGetUnknownPCopy(X) ((unknown *) PG_DETOAST_DATUM_COPY(X))
|
||||
#define PG_GETARG_UNKNOWN_P(n) DatumGetUnknownP(PG_GETARG_DATUM(n))
|
||||
#define PG_GETARG_UNKNOWN_P_COPY(n) DatumGetUnknownPCopy(PG_GETARG_DATUM(n))
|
||||
#define PG_RETURN_UNKNOWN_P(x) PG_RETURN_POINTER(x)
|
||||
|
||||
#define PG_TEXTARG_GET_STR(arg_) \
|
||||
DatumGetCString(DirectFunctionCall1(textout, PG_GETARG_DATUM(arg_)))
|
||||
#define PG_TEXT_GET_STR(textp_) \
|
||||
@@ -111,10 +115,10 @@ byteain(PG_FUNCTION_ARGS)
|
||||
|
||||
byte += VARHDRSZ;
|
||||
result = (bytea *) palloc(byte);
|
||||
result->vl_len = byte; /* set varlena length */
|
||||
VARATT_SIZEP(result) = byte; /* set varlena length */
|
||||
|
||||
tp = inputText;
|
||||
rp = result->vl_dat;
|
||||
rp = VARDATA(result);
|
||||
while (*tp != '\0')
|
||||
{
|
||||
if (tp[0] != '\\')
|
||||
@@ -170,8 +174,8 @@ byteaout(PG_FUNCTION_ARGS)
|
||||
int len;
|
||||
|
||||
len = 1; /* empty string has 1 char */
|
||||
vp = vlena->vl_dat;
|
||||
for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
|
||||
vp = VARDATA(vlena);
|
||||
for (i = VARSIZE(vlena) - VARHDRSZ; i != 0; i--, vp++)
|
||||
{
|
||||
if (*vp == '\\')
|
||||
len += 2;
|
||||
@@ -181,8 +185,8 @@ byteaout(PG_FUNCTION_ARGS)
|
||||
len += 4;
|
||||
}
|
||||
rp = result = (char *) palloc(len);
|
||||
vp = vlena->vl_dat;
|
||||
for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
|
||||
vp = VARDATA(vlena);
|
||||
for (i = VARSIZE(vlena) - VARHDRSZ; i != 0; i--, vp++)
|
||||
{
|
||||
if (*vp == '\\')
|
||||
{
|
||||
@@ -207,6 +211,36 @@ byteaout(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* bytearecv - converts external binary format to bytea
|
||||
*/
|
||||
Datum
|
||||
bytearecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
bytea *result;
|
||||
int nbytes;
|
||||
|
||||
nbytes = buf->len - buf->cursor;
|
||||
result = (bytea *) palloc(nbytes + VARHDRSZ);
|
||||
VARATT_SIZEP(result) = nbytes + VARHDRSZ;
|
||||
pq_copymsgbytes(buf, VARDATA(result), nbytes);
|
||||
PG_RETURN_BYTEA_P(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* byteasend - converts bytea to binary format
|
||||
*
|
||||
* This is a special case: just copy the input...
|
||||
*/
|
||||
Datum
|
||||
byteasend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
bytea *vlena = PG_GETARG_BYTEA_P_COPY(0);
|
||||
|
||||
PG_RETURN_BYTEA_P(vlena);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* textin - converts "..." to internal representation
|
||||
@@ -259,6 +293,39 @@ textout(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* textrecv - converts external binary format to text
|
||||
*/
|
||||
Datum
|
||||
textrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
text *result;
|
||||
char *str;
|
||||
int nbytes;
|
||||
|
||||
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
|
||||
result = (text *) palloc(nbytes + VARHDRSZ);
|
||||
VARATT_SIZEP(result) = nbytes + VARHDRSZ;
|
||||
memcpy(VARDATA(result), str, nbytes);
|
||||
pfree(str);
|
||||
PG_RETURN_TEXT_P(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* textsend - converts text to binary format
|
||||
*/
|
||||
Datum
|
||||
textsend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
text *t = PG_GETARG_TEXT_P(0);
|
||||
StringInfoData buf;
|
||||
|
||||
pq_begintypsend(&buf);
|
||||
pq_sendtext(&buf, VARDATA(t), VARSIZE(t) - VARHDRSZ);
|
||||
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* unknownin - converts "..." to internal representation
|
||||
@@ -280,7 +347,6 @@ unknownin(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_UNKNOWN_P(result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* unknownout - converts internal representation to "..."
|
||||
*/
|
||||
@@ -299,6 +365,37 @@ unknownout(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_CSTRING(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* unknownrecv - converts external binary format to unknown
|
||||
*/
|
||||
Datum
|
||||
unknownrecv(PG_FUNCTION_ARGS)
|
||||
{
|
||||
StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
|
||||
unknown *result;
|
||||
int nbytes;
|
||||
|
||||
nbytes = buf->len - buf->cursor;
|
||||
result = (unknown *) palloc(nbytes + VARHDRSZ);
|
||||
VARATT_SIZEP(result) = nbytes + VARHDRSZ;
|
||||
pq_copymsgbytes(buf, VARDATA(result), nbytes);
|
||||
PG_RETURN_UNKNOWN_P(result);
|
||||
}
|
||||
|
||||
/*
|
||||
* unknownsend - converts unknown to binary format
|
||||
*
|
||||
* This is a special case: just copy the input, since it's
|
||||
* effectively the same format as bytea
|
||||
*/
|
||||
Datum
|
||||
unknownsend(PG_FUNCTION_ARGS)
|
||||
{
|
||||
unknown *vlena = PG_GETARG_UNKNOWN_P_COPY(0);
|
||||
|
||||
PG_RETURN_UNKNOWN_P(vlena);
|
||||
}
|
||||
|
||||
|
||||
/* ========== PUBLIC ROUTINES ========== */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user