Avoid unnecessary copying of parameter values in BIND. This allows
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 12 May 2003 16:48:17 +0000 (16:48 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 12 May 2003 16:48:17 +0000 (16:48 +0000)
efficient insertion of large bytea values through the BIND interface.

src/backend/tcop/postgres.c

index f444302e9651d8b72955aa65e32e8f9daa6c0a90..a37ed5a9b692c20ea0d83cdc121879d39237d770 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.342 2003/05/09 18:08:48 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.343 2003/05/12 16:48:17 tgl Exp $
  *
  * NOTES
  *       this is the "main" module of the postgres backend and
@@ -1265,13 +1265,9 @@ exec_bind_message(StringInfo input_message)
        if (numParams > 0)
        {
                bool    isaborted = IsAbortedTransactionBlockState();
-               StringInfoData pbuf;
                List   *l;
                MemoryContext oldContext;
 
-               /* Note that the string buffer lives in MessageContext */
-               initStringInfo(&pbuf);
-
                oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
 
                params = (ParamListInfo)
@@ -1289,14 +1285,7 @@ exec_bind_message(StringInfo input_message)
 
                        if (!isNull)
                        {
-                               /* Reset pbuf to empty, and insert raw data into it */
-                               pbuf.len = 0;
-                               pbuf.data[0] = '\0';
-                               pbuf.cursor = 0;
-
-                               appendBinaryStringInfo(&pbuf,
-                                                                          pq_getmsgbytes(input_message, plength),
-                                                                          plength);
+                               const char *pvalue = pq_getmsgbytes(input_message, plength);
 
                                if (isaborted)
                                {
@@ -1306,6 +1295,8 @@ exec_bind_message(StringInfo input_message)
                                else
                                {
                                        int16   pformat;
+                                       StringInfoData pbuf;
+                                       char    csave;
 
                                        if (numPFormats > 1)
                                                pformat = pformats[i];
@@ -1314,6 +1305,23 @@ exec_bind_message(StringInfo input_message)
                                        else
                                                pformat = 0;            /* default = text */
 
+                                       /*
+                                        * Rather than copying data around, we just set up a phony
+                                        * StringInfo pointing to the correct portion of the
+                                        * message buffer.  We assume we can scribble on the
+                                        * message buffer so as to maintain the convention that
+                                        * StringInfos have a trailing null.  This is grotty but
+                                        * is a big win when dealing with very large parameter
+                                        * strings.
+                                        */
+                                       pbuf.data = (char *) pvalue;
+                                       pbuf.maxlen = plength + 1;
+                                       pbuf.len = plength;
+                                       pbuf.cursor = 0;
+
+                                       csave = pbuf.data[plength];
+                                       pbuf.data[plength] = '\0';
+
                                        if (pformat == 0)
                                        {
                                                Oid                     typInput;
@@ -1322,11 +1330,8 @@ exec_bind_message(StringInfo input_message)
 
                                                getTypeInputInfo(ptype, &typInput, &typElem);
                                                /*
-                                                * Since stringinfo.c keeps a trailing null in
-                                                * place even for binary data, the contents of
-                                                * pbuf are a valid C string.  We have to do
-                                                * encoding conversion before calling the typinput
-                                                * routine, though.
+                                                * We have to do encoding conversion before calling
+                                                * the typinput routine.
                                                 */
                                                pstring = (char *)
                                                        pg_client_to_server((unsigned char *) pbuf.data,
@@ -1362,6 +1367,9 @@ exec_bind_message(StringInfo input_message)
                                        {
                                                elog(ERROR, "Invalid format code %d", pformat);
                                        }
+
+                                       /* Restore message buffer contents */
+                                       pbuf.data[plength] = csave;
                                }
                        }
 
@@ -2524,7 +2532,7 @@ PostgresMain(int argc, char *argv[], const char *username)
        if (!IsUnderPostmaster)
        {
                puts("\nPOSTGRES backend interactive interface ");
-               puts("$Revision: 1.342 $ $Date: 2003/05/09 18:08:48 $\n");
+               puts("$Revision: 1.343 $ $Date: 2003/05/12 16:48:17 $\n");
        }
 
        /*