@@ -623,7 +623,27 @@ async Task<bool> NextResultSchemaOnly(bool async, bool isConsuming = false, Canc
623623 }
624624 else
625625 {
626+ var pStatement = statement . PreparedStatement ;
627+ if ( pStatement != null )
628+ {
629+ Debug . Assert ( ! pStatement . IsPrepared ) ;
630+ if ( pStatement. StatementBeingReplaced != null )
631+ {
632+ Expect< CloseCompletedMessage> ( await Connector. ReadMessage( async) , Connector ) ;
633+ pStatement . StatementBeingReplaced . CompleteUnprepare ( ) ;
634+ pStatement . StatementBeingReplaced = null ;
635+ }
636+ }
637+
626638 Expect < ParseCompleteMessage > ( await Connector . ReadMessage ( async) , Connector ) ;
639+
640+ if ( statement . IsPreparing )
641+ {
642+ pStatement! . State = PreparedState. Prepared;
643+ Connector. PreparedStatementManager. NumPrepared++ ;
644+ statement. IsPreparing = false;
645+ }
646+
627647 Expect< ParameterDescriptionMessage> ( await Connector. ReadMessage( async) , Connector ) ;
628648 var msg = await Connector . ReadMessage ( async) ;
629649 switch ( msg . Code )
@@ -659,12 +679,31 @@ async Task<bool> NextResultSchemaOnly(bool async, bool isConsuming = false, Canc
659679 {
660680 State = ReaderState. Consumed;
661681
662- // Reference the triggering statement from the exception (for batching)
663- if ( e is PostgresException postgresException &&
664- Command. IsWrappedByBatch &&
665- StatementIndex >= 0 && StatementIndex < _statements. Count)
682+ // Reference the triggering statement from the exception
683+ if ( e is PostgresException postgresException && StatementIndex >= 0 && StatementIndex < _statements. Count)
666684 {
667685 postgresException. BatchCommand = _statements[ StatementIndex] ;
686+
687+ // Prevent the command or batch from by recycled (by the connection) when it's disposed. This is important since
688+ // the exception is very likely to escape the using statement of the command, and by that time some other user may
689+ // already be using the recycled instance.
690+ if ( ! Command. IsWrappedByBatch)
691+ {
692+ Command. IsCached = false;
693+ }
694+ }
695+
696+ // An error means all subsequent statements were skipped by PostgreSQL.
697+ // If any of them were being prepared, we need to update our bookkeeping to put
698+ // them back in unprepared state.
699+ for ( ; StatementIndex < _statements. Count; StatementIndex++ )
700+ {
701+ var statement = _statements[ StatementIndex] ;
702+ if ( statement. IsPreparing)
703+ {
704+ statement. IsPreparing = false;
705+ statement. PreparedStatement! . AbortPrepare( ) ;
706+ }
668707 }
669708
670709 throw ;
0 commit comments