Currently libpq provides a function to escape byteas to include directly in the query string. But if you're using PQexecParam you still need to do one layer of quoting but don't need to double the backslashes which PQescapeBytea does if you have standard_conforming_strings set off.
Do we want something like this which provides a PQescapeByteaParam for escaping bytea strings before passing them as text-mode parameters in PQexecParam? I cheated here and just passed true to standard_conforming_strings which happens to do what we want. It might be better to provide an additional parameter to PQescapeByteaInternal which tells it to only escape \ and NUL and not other binary characters and '. I didn't document it yet, I'll do that if people agree we want it.
Index: src/interfaces/libpq/fe-exec.c =================================================================== RCS file: /home/stark/src/REPOSITORY/pgsql/src/interfaces/libpq/fe-exec.c,v retrieving revision 1.192 diff -c -r1.192 fe-exec.c *** src/interfaces/libpq/fe-exec.c 5 Jan 2007 22:20:01 -0000 1.192 --- src/interfaces/libpq/fe-exec.c 4 Jul 2007 15:06:42 -0000 *************** *** 2803,2808 **** --- 2803,2829 ---- static_std_strings); } + /* ByteaA's have to be escaped even when passing them as text-mode parameters + * because text-mode parameters are null-terminated strings. Confusingly *this* + * is the actual inverse of PQunescapeBytea, *not* PQescapeBytea which does an + * extra layer of quoting to make the result amenable to being inserted into a + * query directly. + */ + + unsigned char * + PQescapeByteaParam(const unsigned char *from, size_t from_length, size_t *to_length) + { + /* + * Passing true for std_strings happens to be sufficient because we quote + * single-quotes as octals so std_strings *never* have to quote anything + * extra beyond quoting binary characters. We only really have to quote + * nuls but quoting all binary characters and single quotes as well will + * satisfy requirements. + */ + + return PQescapeByteaInternal(NULL, from, from_length, to_length, true); + } + #define ISFIRSTOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '3') #define ISOCTDIGIT(CH) ((CH) >= '0' && (CH) <= '7') Index: src/interfaces/libpq/libpq-fe.h =================================================================== RCS file: /home/stark/src/REPOSITORY/pgsql/src/interfaces/libpq/libpq-fe.h,v retrieving revision 1.136 diff -c -r1.136 libpq-fe.h *** src/interfaces/libpq/libpq-fe.h 3 Mar 2007 19:52:46 -0000 1.136 --- src/interfaces/libpq/libpq-fe.h 4 Jul 2007 15:18:44 -0000 *************** *** 442,447 **** --- 442,459 ---- extern unsigned char *PQescapeByteaConn(PGconn *conn, const unsigned char *from, size_t from_length, size_t *to_length); + + /* Quote byteas for use a parameter with PQexecParam(). ByteaA's do need to be + * escaped even when passing them as text-mode parameters because text-mode + * parameters are null-terminated strings. */ + unsigned char * + PQescapeByteaParam(const unsigned char *from, size_t from_length, size_t *to_length); + + /* Note that this performs one fewer layer of dequoting than PQescapeBytea + * because it's for dequoting results of queries. Confusingly that makes it the + * inverse of PQescapeByteaParam, not PQescapeByteaConn which has to do an + * extra layer of quoting to make the result amenable to being directly + * inserted into a query. */ extern unsigned char *PQunescapeBytea(const unsigned char *strtext, size_t *retbuflen);
-- Gregory Stark EnterpriseDB http://www.enterprisedb.com
---------------------------(end of broadcast)--------------------------- TIP 7: You can help support the PostgreSQL project by donating at http://www.postgresql.org/about/donate