Re: [HACKERS] libpq and SPI - Mailing list pgsql-hackers

From Bruce Momjian
Subject Re: [HACKERS] libpq and SPI
Date
Msg-id 199903141810.NAA00388@candle.pha.pa.us
Whole thread Raw
In response to Re: [HACKERS] libpq and SPI  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
Reversed out.  Attached is the patch.

> Bruce Momjian <maillist@candle.pha.pa.us> writes:
> > Applied.
> >
> >> Just in case you'd like to see what I was talking about, I am attaching
> >> my patch to src/interfaces/libpq/fe-exec.c to prevent utility functions
> >> called from SPI from locking up the client.
> 
> Uh, I didn't actually believe that that patch was a good idea.  Hacking
> libpq to survive a protocol violation committed by the backend is *not*
> a solution; the correct answer is to fix the backend.  Otherwise we will
> have to discover similar workarounds for other clients that do not
> use libpq (ODBC, for example).
> 
> Please reverse out that patch until someone can find some time to look
> at the issue.  (I will, if no one else does, but it would probably be
> more efficient for someone who already knows something about SPI to
> fix it...)
> 
>             regards, tom lane
> 


--  Bruce Momjian                        |  http://www.op.net/~candle maillist@candle.pha.pa.us            |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026 
--- fe-exec.c.orig    Mon Feb 22 05:03:04 1999
+++ fe-exec.c    Fri Mar  5 06:03:43 1999
@@ -338,6 +338,7 @@parseInput(PGconn *conn){    char        id;
+        static int      pendingT = 0;    /*     * Loop to parse successive complete messages available in the buffer.
@@ -406,7 +407,16 @@                                                           PGRES_COMMAND_OK);                    if
(pqGets(conn->result->cmdStatus,CMDSTATUS_LEN, conn))                        return;
 
-                    conn->asyncStatus = PGASYNC_READY;
+                                        if (pendingT) {
+                                            /* Check the returned message */
+                                            /* if it's a SELECT or FETCH in a pendingT case, */
+                                            /* then it probably means no rows returned. */
+                                            /* We clear pendingT in that case. */
+                                            if ((strncmp(conn->result->cmdStatus, "SELECT", 6) == 0) ||
+                                                (strncmp(conn->result->cmdStatus, "FETCH",  5) == 0))
+                                                pendingT = 0;
+                                        }
+                    if (!pendingT) conn->asyncStatus = PGASYNC_READY;                    break;                case
'E':       /* error return */                    if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, conn))
 
@@ -416,10 +426,11 @@                    /* and build an error result holding the error message */
conn->result= PQmakeEmptyPGresult(conn,                                                       PGRES_FATAL_ERROR);
 
-                    conn->asyncStatus = PGASYNC_READY;
+                    if (!pendingT) conn->asyncStatus = PGASYNC_READY;                    break;                case
'Z':       /* backend is ready for new query */                    conn->asyncStatus = PGASYNC_IDLE;
 
+                                        pendingT = 0;                    break;                case 'I':        /*
emptyquery */                    /* read and throw away the closing '\0' */
 
@@ -434,7 +445,7 @@                    if (conn->result == NULL)                        conn->result =
PQmakeEmptyPGresult(conn,                                                          PGRES_EMPTY_QUERY);
 
-                    conn->asyncStatus = PGASYNC_READY;
+                    if (!pendingT) conn->asyncStatus = PGASYNC_READY;                    break;                case
'K':       /* secret key data from the backend */
 
@@ -455,11 +466,15 @@                    break;                case 'T':        /* row descriptions (start of query
                           * results) */
 
+                                        if (pendingT) {
+                                            DONOTICE(conn, "Got second 'T' message!\n");
+                                        }                    if (conn->result == NULL)                    {
           /* First 'T' in a query sequence */                        if (getRowDescriptions(conn))
      return;
 
+                                                pendingT = 1;                    }                    else
      {
 
@@ -471,11 +486,13 @@                         * We stop parsing until the application accepts                         *
thecurrent result.                         */
 
+                                                pendingT = 0;                        conn->asyncStatus =
PGASYNC_READY;                       return;                    }                    break;                case 'D':
   /* ASCII data tuple */
 
+                                        pendingT = 0;                    if (conn->result != NULL)
{                       /* Read another tuple of a normal query response */
 
@@ -493,6 +510,7 @@                    }                    break;                case 'B':        /* Binary data tuple
*/
+                                        pendingT = 0;                    if (conn->result != NULL)
{                       /* Read another tuple of a normal query response */
 
@@ -510,12 +528,15 @@                    }                    break;                case 'G':        /* Start Copy In
*/
+                                        pendingT = 0;                    conn->asyncStatus = PGASYNC_COPY_IN;
         break;                case 'H':        /* Start Copy Out */
 
+                                        pendingT = 0;                    conn->asyncStatus = PGASYNC_COPY_OUT;
          break;                default:
 
+                                        pendingT = 0;                    sprintf(conn->errorMessage,
"unknown protocol character '%c' read from backend.  "                    "(The protocol character is the first
characterthe " 

pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: [HACKERS] Problems with >2GB tables on Linux 2.0
Next
From: Tom Lane
Date:
Subject: Re: [HACKERS] libpq and SPI