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: