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

Reply via email to