From 05257fb864895b5f2414620e5b8ca74a1a1c826b Mon Sep 17 00:00:00 2001
From: "Stephen R. van den Berg" <srb@cuci.nl>
Date: Fri, 4 Jul 2008 11:38:40 +0200
Subject: [PATCH] Autodetect binary transfer for postgres.c

Rev: lib/modules/Sql.pmod/postgres.pike:1.31
Rev: src/modules/Postgres/pg_types.h:1.11
Rev: src/modules/Postgres/postgres.c:1.63
---
 lib/modules/Sql.pmod/postgres.pike |  9 +++---
 src/modules/Postgres/pg_types.h    |  4 ++-
 src/modules/Postgres/postgres.c    | 47 ++++++++++++++++++------------
 3 files changed, 36 insertions(+), 24 deletions(-)

diff --git a/lib/modules/Sql.pmod/postgres.pike b/lib/modules/Sql.pmod/postgres.pike
index 21b51ce8ad..3310b487fd 100644
--- a/lib/modules/Sql.pmod/postgres.pike
+++ b/lib/modules/Sql.pmod/postgres.pike
@@ -1,7 +1,7 @@
 /*
  * This is part of the Postgres module for Pike.
  *
- * $Id: postgres.pike,v 1.30 2008/07/04 08:25:39 srb Exp $
+ * $Id: postgres.pike,v 1.31 2008/07/04 09:38:40 srb Exp $
  *
  */
 
@@ -389,7 +389,7 @@ int|object big_query(object|string q, mapping(string|int:mixed)|void bindings)
   if (!bindings)
     return ::big_query(q);
   int pi=0,rep=0;
-  array(string|int) paramValues=allocate(sizeof(bindings)*2);
+  array(string|int) paramValues=allocate(sizeof(bindings));
   array(string) from=allocate(sizeof(bindings));
   array(string) to=allocate(sizeof(bindings));
   foreach(bindings; mixed name; mixed value) {
@@ -408,15 +408,14 @@ int|object big_query(object|string q, mapping(string|int:mixed)|void bindings)
       rval=sizeof(value) ? indices(value)[0] : "";
     }
     else {
-      paramValues[pi++]=name[sizeof(name)-1]=='_'; // Force binary mode
-      if(zero_type(value))			   // when name ends in _
+      if(zero_type(value))
         paramValues[pi++]=UNDEFINED;
       else {
         if(stringp(value) && String.width(value)>8)
           value=string_to_utf8(value);
         paramValues[pi++]=(string)value;
       }
-      rval="$"+(string)(pi/2);
+      rval="$"+(string)pi;
     }
     to[rep++]=rval;
   }
diff --git a/src/modules/Postgres/pg_types.h b/src/modules/Postgres/pg_types.h
index 06437ec87c..b334f7042a 100644
--- a/src/modules/Postgres/pg_types.h
+++ b/src/modules/Postgres/pg_types.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: pg_types.h,v 1.10 2008/06/23 14:24:25 srb Exp $
+|| $Id: pg_types.h,v 1.11 2008/07/04 09:38:40 srb Exp $
 */
 
 #ifndef _PG_TYPES_H_
@@ -38,4 +38,6 @@ extern struct program *postgres_program, *pgresult_program;
 #define CURSORNAME	"_pikecursor"
 #define FETCHCMD	"FETCH " FETCHSIZESTR " IN " CURSORNAME
 
+#define BINARYCUTOFF	32	 /* binding parameters at least this size
+				    are presumed to be in binary format */
 #endif
diff --git a/src/modules/Postgres/postgres.c b/src/modules/Postgres/postgres.c
index 02d467556a..3e5520383e 100644
--- a/src/modules/Postgres/postgres.c
+++ b/src/modules/Postgres/postgres.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: postgres.c,v 1.62 2008/07/04 08:25:39 srb Exp $
+|| $Id: postgres.c,v 1.63 2008/07/04 09:38:40 srb Exp $
 */
 
 /*
@@ -420,35 +420,46 @@ static void f_big_query(INT32 args)
           int i;
 	  struct svalue *item;
 
-	  if(cnt & 1)
-	    Pike_error ("Uneven number of arrayelements.\n");
-
-	  nParams=cnt=cnt/2;
+	  nParams=cnt;
 	  
-	  paramValues = xalloc(cnt*sizeof*paramValues);
-	  paramLengths = xalloc(cnt*sizeof*paramLengths);
-	  paramFormats = xalloc(cnt*sizeof*paramFormats);
+	  paramValues = xalloc(nParams*sizeof*paramValues);
+	  paramLengths = xalloc(nParams*sizeof*paramLengths);
+	  paramFormats = xalloc(nParams*sizeof*paramFormats);
 
 	  for (i=0,item=bnds->item; cnt--; item++,i++) {
-
-	    if (item->type != PIKE_T_INT)
-	      Pike_error ("Expected integer element.\n");
-	    paramFormats[i] = item->u.integer ? 1 : 0;
-	    switch((++item)->type)
-	    { case PIKE_T_STRING:
-	          paramValues[i] = item->u.string->str;
-		  paramLengths[i] = item->u.string->len;
+	    int sendbin=0;
+	    switch(item->type)
+	    { case PIKE_T_STRING: {
+	          long len;
+		  const char*p;
+		  paramLengths[i] = len = item->u.string->len;
+	          paramValues[i] = p = item->u.string->str;
+	          if( len >= BINARYCUTOFF)
+	            sendbin = 1;
+	          else {
+	            while(len--) {
+		      switch(*p++) {
+			default:
+			  continue;
+			case '\0':case '\\':
+			  sendbin = 1;
+		      }
+		      break;
+		    }
+	          }
 	        break;
+	      }
 	      case PIKE_T_INT:
 	      case T_VOID:
 	          paramValues[i] = 0;	     /* NULL */
 		  paramLengths[i] = 0;
 	        break;
 	      default:
-                  Pike_error ("Expected string or UNDEFINED element, Got %d.\n",
- item->type);
+                  Pike_error("Expected string or UNDEFINED element, Got %d.\n",
+		   item->type);
 	        break;
 	    }
+	    paramFormats[i] = sendbin;
 	  }
         }
 
-- 
GitLab