From d99e6e2b05f03ed2515ee7369b8b9d44cfe2ac40 Mon Sep 17 00:00:00 2001
From: "Stephen R. van den Berg" <srb@cuci.nl>
Date: Mon, 10 Jul 2017 13:44:33 +0200
Subject: [PATCH] pgsql: Support multiset binary literals and avoid copying
 Stdio.Buffer() bindings.

---
 lib/modules/Sql.pmod/pgsql_util.pmod | 34 ++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/lib/modules/Sql.pmod/pgsql_util.pmod b/lib/modules/Sql.pmod/pgsql_util.pmod
index 8a397227e1..7094634188 100644
--- a/lib/modules/Sql.pmod/pgsql_util.pmod
+++ b/lib/modules/Sql.pmod/pgsql_util.pmod
@@ -32,6 +32,7 @@ final multiset censoroptions=(<"use_ssl","force_ssl",
  "cache_autoprepared_statements","reconnect","text_query","is_superuser",
  "server_encoding","server_version","integer_datetimes",
  "session_authorization">);
+constant stdiobuftype = typeof(Stdio.Buffer());
 
  /* Statements matching createprefix cause the prepared statement cache
   * to be flushed to prevent stale references to (temporary) tables
@@ -879,15 +880,30 @@ class sql_result {
                 plugbuffer->add_int32(-1);
                 break;
               }
-              value=(string)value;
-              if(String.width(value)>8)
-                if(dtoid[i]==BYTEAOID)
-                  value=string_to_utf8(value);
-                else {
-                  SUSERERROR("Wide string %O not supported for type OID %d\n",
-                             value,dtoid[i]);
-                  value="";
-                }
+	      if (!objectp(value) || typeof(value) != stdiobuftype)
+	        /*
+	         *  Like Oracle and SQLite, we accept literal binary values
+	         *  from single-valued multisets.
+	         */
+	        if (multisetp(value) && sizeof(value) == 1)
+	          value = indices(value)[0];
+	        else {
+                  value = (string)value;
+                  if (String.width(value) > 8)
+                    if (dtoid[i] == BYTEAOID)
+	              /*
+                       *  FIXME We should throw an error here, it would
+		       *  have been correct, but for historical reasons and
+		       *  as a DWIM convenience we autoconvert to UTF8 here.
+                       */
+                      value = string_to_utf8(value);
+                    else {
+                      SUSERERROR(
+	                "Wide string %O not supported for type OID %d\n",
+                        value,dtoid[i]);
+                      value="";
+                    }
+	        }
               plugbuffer->add_hstring(value,4);
               break;
             }
-- 
GitLab