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)
278278 return ;
279279 break ;
280280 case '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 */
285294 if (getRowDescriptions (conn , msgLength ))
@@ -329,9 +338,10 @@ pqParseInput3(PGconn *conn)
329338 }
330339 break ;
331340 case 't' : /* Parameter Description */
332- if (getParamDescriptions (conn ))
341+ if (getParamDescriptions (conn , msgLength ))
333342 return ;
334- break ;
343+ /* getParamDescriptions() moves inStart itself */
344+ continue ;
335345 case 'D' : /* Data Row */
336346 if (conn -> result != NULL &&
337347 conn -> 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{
642652 PGresult * result ;
643653 int nparams ;
644654 int i ;
655+ const char * errmsg = NULL ;
645656
646657 result = PQmakeEmptyPGresult (conn , PGRES_COMMAND_OK );
647658 if (!result )
648- goto failure ;
659+ goto advance_and_error ;
649660
650661 /* parseInput already read the 't' label and message length. */
651662 /* the next two bytes are the number of parameters */
652663 if (pqGetInt (& (result -> numParameters ), 2 , conn ))
653- goto failure ;
664+ goto not_enough_data ;
654665 nparams = result -> numParameters ;
655666
656667 /* allocate space for the parameter descriptors */
@@ -659,7 +670,7 @@ getParamDescriptions(PGconn *conn)
659670 result -> paramDescs = (PGresParamDesc * )
660671 pqResultAlloc (result , nparams * sizeof (PGresParamDesc ), TRUE);
661672 if (!result -> paramDescs )
662- goto failure ;
673+ goto advance_and_error ;
663674 MemSet (result -> paramDescs , 0 , nparams * sizeof (PGresParamDesc ));
664675 }
665676
@@ -669,17 +680,48 @@ getParamDescriptions(PGconn *conn)
669680 int typid ;
670681
671682 if (pqGetInt (& typid , 4 , conn ))
672- goto failure ;
683+ goto not_enough_data ;
673684 result -> paramDescs [i ].typid = typid ;
674685 }
675686
676687 /* Success! */
677688 conn -> result = result ;
689+
690+ /* Advance inStart to show that the "t" message has been processed. */
691+ conn -> inStart = conn -> inCursor ;
692+
678693 return 0 ;
679694
680- failure :
695+ not_enough_data :
681696 PQclear (result );
682697 return 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/*
0 commit comments