Add PQunescapeBytea libpq function.

Everyone using libpq and bytea is probably having to invent this wheel..

Patrick Welche
This commit is contained in:
Bruce Momjian 2002-03-04 23:59:14 +00:00
parent b2aade0e4b
commit 294f0d4bd6
4 changed files with 137 additions and 25 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.87 2002/01/18 20:39:04 momjian Exp $ $Header: /cvsroot/pgsql/doc/src/sgml/libpq.sgml,v 1.88 2002/03/04 23:59:11 momjian Exp $
--> -->
<chapter id="libpq"> <chapter id="libpq">
@ -955,6 +955,25 @@ strings overlap.
byte is also added. The single quotes that must surround byte is also added. The single quotes that must surround
PostgreSQL string literals are not part of the result string. PostgreSQL string literals are not part of the result string.
</para> </para>
<para>
<function>PQunescapeBytea</function>
Converts an escaped string representation of binary data into binary
data - the reverse of <function>PQescapeBytea</function>.
<synopsis>
unsigned char *PQunescapeBytea(unsigned char *from, size_t *to_length);
</synopsis>
The <paramater>from</parameter> parameter points to an escaped string
such as might be returned by <function>PQgetvalue</function> of a
<type>BYTEA</type> column. <function>PQunescapeBytea</function> converts
this NUL terminated string representation into binary, filling a buffer.
It returns a pointer to the buffer which is NULL on error, and the size
of the buffer in <parameter>to_length</parameter>. The pointer may
subsequently be used as an argument to the function
<function>free(3)</function>.
</para>
</sect2> </sect2>

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: elog.h,v 1.32 2002/03/04 01:46:04 tgl Exp $ * $Id: elog.h,v 1.33 2002/03/04 23:59:14 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -15,27 +15,28 @@
#define ELOG_H #define ELOG_H
/* Error level codes */ /* Error level codes */
#define DEBUG5 10 /* Debugging messages, in categories #define DEBUG5 10 /* Debugging messages, in categories
* of decreasing detail. */ * of decreasing detail. */
#define DEBUG4 11 #define DEBUG4 11
#define DEBUG3 12 #define DEBUG3 12
#define DEBUG2 13 #define DEBUG2 13
#define DEBUG1 14 #define DEBUG1 14
#define LOG 15 /* Server operational history messages; #define LOG 15 /* Server operational history messages;
* sent only to server log by default. */ * sent only to server log by default. */
#define COMMERROR 16 /* Client communication problems; same as #define COMMERROR 16 /* Client communication problems; same as
* LOG for server reporting, but never ever * LOG for server reporting, but never ever
* try to send to client. */ * try to send to client. */
#define INFO 17 /* Informative messages that are part of #define INFO 17 /* Informative messages that are part of
* normal query operation; sent only to * normal query operation; sent only to
* client by default. */ * client by default. */
#define NOTICE 18 /* Important messages, for unusual cases that #define INFOALWAYS 18 /* Like INFO, but always prints to client */
* should be reported but are not serious #define NOTICE 19 /* Important messages, for unusual cases that
* enough to abort the query. Sent to client * should be reported but are not serious
* and server log by default. */ * enough to abort the query. Sent to client
#define ERROR 19 /* user error - return to known state */ * and server log by default. */
#define FATAL 20 /* fatal error - abort process */ #define ERROR 20 /* user error - return to known state */
#define PANIC 21 /* take down the other backends with me */ #define FATAL 21 /* fatal error - abort process */
#define PANIC 22 /* take down the other backends with me */
/*#define DEBUG DEBUG1*/ /* Backward compatibility with pre-7.3 */ /*#define DEBUG DEBUG1*/ /* Backward compatibility with pre-7.3 */

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.113 2001/10/25 05:50:13 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.114 2002/03/04 23:59:14 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -180,6 +180,95 @@ PQescapeBytea(unsigned char *bintext, size_t binlen, size_t *bytealen)
return result; return result;
} }
/*
* PQunescapeBytea - converts the null terminated string representation
* of a bytea, strtext, into binary, filling a buffer. It returns a
* pointer to the buffer which is NULL on error, and the size of the
* buffer in retbuflen. The pointer may subsequently be used as an
* argument to the function free(3). It is the reverse of PQescapeBytea.
*
* The following transformations are reversed:
* '\0' == ASCII 0 == \000
* '\'' == ASCII 39 == \'
* '\\' == ASCII 92 == \\
*
* States:
* 0 normal 0->1->2->3->4
* 1 \ 1->5
* 2 \0 1->6
* 3 \00
* 4 \000
* 5 \'
* 6 \\
*/
unsigned char *
PQunescapeBytea(unsigned char *strtext, size_t *retbuflen)
{
size_t buflen;
unsigned char *buffer, *sp, *bp;
unsigned int state=0;
if(strtext == NULL)return NULL;
buflen = strlen(strtext); /* will shrink, also we discover if strtext */
buffer = (unsigned char *) malloc(buflen); /* isn't NULL terminated */
if(buffer == NULL)return NULL;
for(bp = buffer, sp = strtext; *sp != '\0'; bp++, sp++)
{
switch(state)
{
case 0:
if(*sp == '\\')state=1;
*bp = *sp;
break;
case 1:
if(*sp == '\'') /* state=5 */
{ /* replace \' with 39 */
bp--;
*bp = 39;
buflen--;
state=0;
}
else if(*sp == '\\') /* state=6 */
{ /* replace \\ with 92 */
bp--;
*bp = 92;
buflen--;
state=0;
}
else
{
if(*sp == '0')state=2;
else state=0;
*bp = *sp;
}
break;
case 2:
if(*sp == '0')state=3;
else state=0;
*bp = *sp;
break;
case 3:
if(*sp == '0') /* state=4 */
{
bp -= 3;
*bp = 0;
buflen -= 3;
state=0;
}
else
{
*bp = *sp;
state=0;
}
break;
}
}
realloc(buffer,buflen);
*retbuflen=buflen;
return buffer;
}
/* ---------------- /* ----------------
* Space management for PGresult. * Space management for PGresult.
* *

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $Id: libpq-fe.h,v 1.80 2001/11/08 20:37:52 momjian Exp $ * $Id: libpq-fe.h,v 1.81 2002/03/04 23:59:14 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -252,6 +252,9 @@ extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn,
extern size_t PQescapeString(char *to, const char *from, size_t length); extern size_t PQescapeString(char *to, const char *from, size_t length);
extern unsigned char *PQescapeBytea(unsigned char *bintext, size_t binlen, extern unsigned char *PQescapeBytea(unsigned char *bintext, size_t binlen,
size_t *bytealen); size_t *bytealen);
extern unsigned char *PQunescapeBytea(unsigned char *strtext,
size_t *retbuflen);
/* Simple synchronous query */ /* Simple synchronous query */
extern PGresult *PQexec(PGconn *conn, const char *query); extern PGresult *PQexec(PGconn *conn, const char *query);