4545
4646static void handleSyncLoss (PGconn * conn ,char id ,int msgLength );
4747static int getRowDescriptions (PGconn * conn ,int msgLength );
48- static int getParamDescriptions (PGconn * conn );
48+ static int getParamDescriptions (PGconn * conn , int msgLength );
4949static int getAnotherTuple (PGconn * conn ,int msgLength );
5050static int getParameterStatus (PGconn * conn );
5151static int getNotify (PGconn * conn );
@@ -278,8 +278,17 @@ pqParseInput3(PGconn *conn)
278278return ;
279279break ;
280280case 'T' :/* Row Description */
281- if (conn -> result == NULL ||
282- conn -> queryclass == PGQUERY_DESCRIBE )
281+ if (conn -> result != NULL &&
282+ conn -> result -> resultStatus == PGRES_FATAL_ERROR )
283+ {
284+ /*
285+ * We've already choked for some reason. Just discard
286+ * the data till we get to the end of the query.
287+ */
288+ conn -> inCursor += msgLength ;
289+ }
290+ else if (conn -> result == NULL ||
291+ conn -> queryclass == PGQUERY_DESCRIBE )
283292{
284293/* First 'T' in a query sequence */
285294if (getRowDescriptions (conn ,msgLength ))
@@ -329,9 +338,10 @@ pqParseInput3(PGconn *conn)
329338}
330339break ;
331340case 't' :/* Parameter Description */
332- if (getParamDescriptions (conn ))
341+ if (getParamDescriptions (conn , msgLength ))
333342return ;
334- break ;
343+ /* getParamDescriptions() moves inStart itself */
344+ continue ;
335345case 'D' :/* Data Row */
336346if (conn -> result != NULL &&
337347conn -> result -> resultStatus == PGRES_TUPLES_OK )
@@ -637,20 +647,21 @@ getRowDescriptions(PGconn *conn, int msgLength)
637647 * that shouldn't happen often, since 't' messages usually fit in a packet.
638648 */
639649static int
640- getParamDescriptions (PGconn * conn )
650+ getParamDescriptions (PGconn * conn , int msgLength )
641651{
642652PGresult * result ;
643653int nparams ;
644654int i ;
655+ const char * errmsg = NULL ;
645656
646657result = PQmakeEmptyPGresult (conn ,PGRES_COMMAND_OK );
647658if (!result )
648- gotofailure ;
659+ gotoadvance_and_error ;
649660
650661/* parseInput already read the 't' label and message length. */
651662/* the next two bytes are the number of parameters */
652663if (pqGetInt (& (result -> numParameters ),2 ,conn ))
653- gotofailure ;
664+ gotonot_enough_data ;
654665nparams = result -> numParameters ;
655666
656667/* allocate space for the parameter descriptors */
@@ -659,7 +670,7 @@ getParamDescriptions(PGconn *conn)
659670result -> paramDescs = (PGresParamDesc * )
660671pqResultAlloc (result ,nparams * sizeof (PGresParamDesc ), TRUE);
661672if (!result -> paramDescs )
662- gotofailure ;
673+ gotoadvance_and_error ;
663674MemSet (result -> paramDescs ,0 ,nparams * sizeof (PGresParamDesc ));
664675}
665676
@@ -669,17 +680,48 @@ getParamDescriptions(PGconn *conn)
669680int typid ;
670681
671682if (pqGetInt (& typid ,4 ,conn ))
672- gotofailure ;
683+ gotonot_enough_data ;
673684result -> paramDescs [i ].typid = typid ;
674685}
675686
676687/* Success! */
677688conn -> result = result ;
689+
690+ /* Advance inStart to show that the "t" message has been processed. */
691+ conn -> inStart = conn -> inCursor ;
692+
678693return 0 ;
679694
680- failure :
695+ not_enough_data :
681696PQclear (result );
682697return EOF ;
698+
699+ advance_and_error :
700+ /* Discard unsaved result, if any */
701+ if (result && result != conn -> result )
702+ PQclear (result );
703+
704+ /* Discard the failed message by pretending we read it */
705+ conn -> inStart += 5 + msgLength ;
706+
707+ /*
708+ * Replace partially constructed result with an error result. First
709+ * discard the old result to try to win back some memory.
710+ */
711+ pqClearAsyncResult (conn );
712+
713+ /*
714+ * If preceding code didn't provide an error message, assume "out of
715+ * memory" was meant. The advantage of having this special case is that
716+ * freeing the old result first greatly improves the odds that gettext()
717+ * will succeed in providing a translation.
718+ */
719+ if (!errmsg )
720+ errmsg = libpq_gettext ("out of memory" );
721+ printfPQExpBuffer (& conn -> errorMessage ,"%s\n" ,errmsg );
722+ pqSaveErrorResult (conn );
723+
724+ return 0 ;
683725}
684726
685727/*