Commit e2c4d41f authored by Bruce Momjian's avatar Bruce Momjian

Hi,

    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.

Jerry Gay
parent 80db587e
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.74 1999/02/13 23:22:41 momjian Exp $ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.75 1999/03/14 16:42:15 momjian Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -467,6 +467,7 @@ static void ...@@ -467,6 +467,7 @@ static void
parseInput(PGconn *conn) parseInput(PGconn *conn)
{ {
char id; char id;
static int pendingT = 0;
/* /*
* Loop to parse successive complete messages available in the buffer. * Loop to parse successive complete messages available in the buffer.
...@@ -535,7 +536,15 @@ parseInput(PGconn *conn) ...@@ -535,7 +536,15 @@ parseInput(PGconn *conn)
PGRES_COMMAND_OK); PGRES_COMMAND_OK);
if (pqGets(conn->result->cmdStatus, CMDSTATUS_LEN, conn)) if (pqGets(conn->result->cmdStatus, CMDSTATUS_LEN, conn))
return; return;
conn->asyncStatus = PGASYNC_READY; if (pendingT) {
/* Check the returned message */
/* if it's a SELECT 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)
pendingT = 0;
}
if (!pendingT) conn->asyncStatus = PGASYNC_READY;
break; break;
case 'E': /* error return */ case 'E': /* error return */
if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, conn)) if (pqGets(conn->errorMessage, ERROR_MSG_LENGTH, conn))
...@@ -545,10 +554,11 @@ parseInput(PGconn *conn) ...@@ -545,10 +554,11 @@ parseInput(PGconn *conn)
/* and build an error result holding the error message */ /* and build an error result holding the error message */
conn->result = PQmakeEmptyPGresult(conn, conn->result = PQmakeEmptyPGresult(conn,
PGRES_FATAL_ERROR); PGRES_FATAL_ERROR);
conn->asyncStatus = PGASYNC_READY; if (!pendingT) conn->asyncStatus = PGASYNC_READY;
break; break;
case 'Z': /* backend is ready for new query */ case 'Z': /* backend is ready for new query */
conn->asyncStatus = PGASYNC_IDLE; conn->asyncStatus = PGASYNC_IDLE;
pendingT = 0;
break; break;
case 'I': /* empty query */ case 'I': /* empty query */
/* read and throw away the closing '\0' */ /* read and throw away the closing '\0' */
...@@ -563,7 +573,7 @@ parseInput(PGconn *conn) ...@@ -563,7 +573,7 @@ parseInput(PGconn *conn)
if (conn->result == NULL) if (conn->result == NULL)
conn->result = PQmakeEmptyPGresult(conn, conn->result = PQmakeEmptyPGresult(conn,
PGRES_EMPTY_QUERY); PGRES_EMPTY_QUERY);
conn->asyncStatus = PGASYNC_READY; if (!pendingT) conn->asyncStatus = PGASYNC_READY;
break; break;
case 'K': /* secret key data from the backend */ case 'K': /* secret key data from the backend */
...@@ -584,11 +594,15 @@ parseInput(PGconn *conn) ...@@ -584,11 +594,15 @@ parseInput(PGconn *conn)
break; break;
case 'T': /* row descriptions (start of query case 'T': /* row descriptions (start of query
* results) */ * results) */
if (pendingT) {
DONOTICE(conn, "Got second 'T' message!\n");
}
if (conn->result == NULL) if (conn->result == NULL)
{ {
/* First 'T' in a query sequence */ /* First 'T' in a query sequence */
if (getRowDescriptions(conn)) if (getRowDescriptions(conn))
return; return;
pendingT = 1;
} }
else else
{ {
...@@ -600,11 +614,13 @@ parseInput(PGconn *conn) ...@@ -600,11 +614,13 @@ parseInput(PGconn *conn)
* We stop parsing until the application accepts * We stop parsing until the application accepts
* the current result. * the current result.
*/ */
pendingT = 0;
conn->asyncStatus = PGASYNC_READY; conn->asyncStatus = PGASYNC_READY;
return; return;
} }
break; break;
case 'D': /* ASCII data tuple */ case 'D': /* ASCII data tuple */
pendingT = 0;
if (conn->result != NULL) if (conn->result != NULL)
{ {
/* Read another tuple of a normal query response */ /* Read another tuple of a normal query response */
...@@ -622,6 +638,7 @@ parseInput(PGconn *conn) ...@@ -622,6 +638,7 @@ parseInput(PGconn *conn)
} }
break; break;
case 'B': /* Binary data tuple */ case 'B': /* Binary data tuple */
pendingT = 0;
if (conn->result != NULL) if (conn->result != NULL)
{ {
/* Read another tuple of a normal query response */ /* Read another tuple of a normal query response */
...@@ -639,12 +656,15 @@ parseInput(PGconn *conn) ...@@ -639,12 +656,15 @@ parseInput(PGconn *conn)
} }
break; break;
case 'G': /* Start Copy In */ case 'G': /* Start Copy In */
pendingT = 0;
conn->asyncStatus = PGASYNC_COPY_IN; conn->asyncStatus = PGASYNC_COPY_IN;
break; break;
case 'H': /* Start Copy Out */ case 'H': /* Start Copy Out */
pendingT = 0;
conn->asyncStatus = PGASYNC_COPY_OUT; conn->asyncStatus = PGASYNC_COPY_OUT;
break; break;
default: default:
pendingT = 0;
sprintf(conn->errorMessage, sprintf(conn->errorMessage,
"unknown protocol character '%c' read from backend. " "unknown protocol character '%c' read from backend. "
"(The protocol character is the first character the " "(The protocol character is the first character the "
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment