45
45
46
46
static void handleSyncLoss (PGconn * conn , char id , int msgLength );
47
47
static int getRowDescriptions (PGconn * conn , int msgLength );
48
- static int getParamDescriptions (PGconn * conn );
48
+ static int getParamDescriptions (PGconn * conn , int msgLength );
49
49
static int getAnotherTuple (PGconn * conn , int msgLength );
50
50
static int getParameterStatus (PGconn * conn );
51
51
static int getNotify (PGconn * conn );
@@ -278,8 +278,17 @@ pqParseInput3(PGconn *conn)
278
278
return ;
279
279
break ;
280
280
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 )
283
292
{
284
293
/* First 'T' in a query sequence */
285
294
if (getRowDescriptions (conn , msgLength ))
@@ -329,9 +338,10 @@ pqParseInput3(PGconn *conn)
329
338
}
330
339
break ;
331
340
case 't' : /* Parameter Description */
332
- if (getParamDescriptions (conn ))
341
+ if (getParamDescriptions (conn , msgLength ))
333
342
return ;
334
- break ;
343
+ /* getParamDescriptions() moves inStart itself */
344
+ continue ;
335
345
case 'D' : /* Data Row */
336
346
if (conn -> result != NULL &&
337
347
conn -> result -> resultStatus == PGRES_TUPLES_OK )
@@ -637,20 +647,21 @@ getRowDescriptions(PGconn *conn, int msgLength)
637
647
* that shouldn't happen often, since 't' messages usually fit in a packet.
638
648
*/
639
649
static int
640
- getParamDescriptions (PGconn * conn )
650
+ getParamDescriptions (PGconn * conn , int msgLength )
641
651
{
642
652
PGresult * result ;
643
653
int nparams ;
644
654
int i ;
655
+ const char * errmsg = NULL ;
645
656
646
657
result = PQmakeEmptyPGresult (conn , PGRES_COMMAND_OK );
647
658
if (!result )
648
- goto failure ;
659
+ goto advance_and_error ;
649
660
650
661
/* parseInput already read the 't' label and message length. */
651
662
/* the next two bytes are the number of parameters */
652
663
if (pqGetInt (& (result -> numParameters ), 2 , conn ))
653
- goto failure ;
664
+ goto not_enough_data ;
654
665
nparams = result -> numParameters ;
655
666
656
667
/* allocate space for the parameter descriptors */
@@ -659,7 +670,7 @@ getParamDescriptions(PGconn *conn)
659
670
result -> paramDescs = (PGresParamDesc * )
660
671
pqResultAlloc (result , nparams * sizeof (PGresParamDesc ), TRUE);
661
672
if (!result -> paramDescs )
662
- goto failure ;
673
+ goto advance_and_error ;
663
674
MemSet (result -> paramDescs , 0 , nparams * sizeof (PGresParamDesc ));
664
675
}
665
676
@@ -669,17 +680,48 @@ getParamDescriptions(PGconn *conn)
669
680
int typid ;
670
681
671
682
if (pqGetInt (& typid , 4 , conn ))
672
- goto failure ;
683
+ goto not_enough_data ;
673
684
result -> paramDescs [i ].typid = typid ;
674
685
}
675
686
676
687
/* Success! */
677
688
conn -> result = result ;
689
+
690
+ /* Advance inStart to show that the "t" message has been processed. */
691
+ conn -> inStart = conn -> inCursor ;
692
+
678
693
return 0 ;
679
694
680
- failure :
695
+ not_enough_data :
681
696
PQclear (result );
682
697
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 ;
683
725
}
684
726
685
727
/*
0 commit comments