Insert into getCopyDataMessage() the same logic that already existed in the
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 17 Jan 2008 21:21:50 +0000 (21:21 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 17 Jan 2008 21:21:50 +0000 (21:21 +0000)
main code path for enlarging libpq's input buffer in one swoop when needing to
read a long data message.  Without this, the code will double the buffer size,
read more data, notice it still hasn't got the whole message, and repeat till
it finally has a large enough buffer.  Which wastes a lot of data-moving
effort and also memory (since malloc probably can't do anything very useful
with the freed-up smaller buffers).  Not sure why this wasn't there already;
certainly the COPY data path is a place where we're quite likely to see long
data messages.  I'm not backpatching though, since this is just a marginal
performance issue rather than a real bug.

src/interfaces/libpq/fe-protocol3.c

index c40868805f33716f825668b4d39473ef020d6fc9..89c0d5018f00d40f66d81ba2d617097b8b8c5bec 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.33 2008/01/15 22:18:20 tgl Exp $
+ *       $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol3.c,v 1.34 2008/01/17 21:21:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1305,7 +1305,24 @@ getCopyDataMessage(PGconn *conn)
                }
                avail = conn->inEnd - conn->inCursor;
                if (avail < msgLength - 4)
+               {
+                       /*
+                        * Before returning, enlarge the input buffer if needed to hold
+                        * the whole message.  See notes in parseInput.
+                        */
+                       if (pqCheckInBufferSpace(conn->inCursor + msgLength - 4, conn))
+                       {
+                               /*
+                                * XXX add some better recovery code... plan is to skip over
+                                * the message using its length, then report an error. For the
+                                * moment, just treat this like loss of sync (which indeed it
+                                * might be!)
+                                */
+                               handleSyncLoss(conn, id, msgLength);
+                               return -2;
+                       }
                        return 0;
+               }
 
                /*
                 * If it's a legitimate async message type, process it.  (NOTIFY