@@ -134,7 +134,6 @@ impl PgConnection {
134134 message if message. format == MessageFormat :: PortalSuspended => {
135135 // there was an open portal
136136 // this can happen if the last time a statement was used it was not fully executed
137- // such as in [fetch_one]
138137 }
139138
140139 message if message. format == MessageFormat :: CloseComplete => {
@@ -219,8 +218,7 @@ impl PgConnection {
219218 // patch holes created during encoding
220219 arguments. apply_patches ( self , & metadata. parameters ) . await ?;
221220
222- // apply patches use fetch_optional thaht may produce `PortalSuspended` message,
223- // consume messages til `ReadyForQuery` before bind and execute
221+ // consume messages till `ReadyForQuery` before bind and execute
224222 self . wait_until_ready ( ) . await ?;
225223
226224 // bind to attach the arguments to the statement and create a portal
@@ -239,6 +237,16 @@ impl PgConnection {
239237 portal : None ,
240238 limit : limit. into ( ) ,
241239 } ) ;
240+ // From https://www.postgresql.org/docs/current/protocol-flow.html:
241+ //
242+ // "An unnamed portal is destroyed at the end of the transaction, or as
243+ // soon as the next Bind statement specifying the unnamed portal as
244+ // destination is issued. (Note that a simple Query message also
245+ // destroys the unnamed portal."
246+
247+ // we ask the database server to close the unnamed portal and free the associated resources
248+ // earlier - after the execution of the current query.
249+ self . stream . write ( message:: Close :: Portal ( None ) ) ;
242250
243251 // finally, [Sync] asks postgres to process the messages that we sent and respond with
244252 // a [ReadyForQuery] message when it's completely done. Theoretically, we could send
@@ -271,10 +279,17 @@ impl PgConnection {
271279 MessageFormat :: BindComplete
272280 | MessageFormat :: ParseComplete
273281 | MessageFormat :: ParameterDescription
274- | MessageFormat :: NoData => {
282+ | MessageFormat :: NoData
283+ // unnamed portal has been closed
284+ | MessageFormat :: CloseComplete
285+ => {
275286 // harmless messages to ignore
276287 }
277288
289+ // "Execute phase is always terminated by the appearance of
290+ // exactly one of these messages: CommandComplete,
291+ // EmptyQueryResponse (if the portal was created from an
292+ // empty query string), ErrorResponse, or PortalSuspended"
278293 MessageFormat :: CommandComplete => {
279294 // a SQL command completed normally
280295 let cc: CommandComplete = message. decode( ) ?;
@@ -290,6 +305,11 @@ impl PgConnection {
290305 // empty query string passed to an unprepared execute
291306 }
292307
308+ // Message::ErrorResponse is handled in self.stream.recv()
309+
310+ // incomplete query execution has finished
311+ MessageFormat :: PortalSuspended => { }
312+
293313 MessageFormat :: RowDescription => {
294314 // indicates that a *new* set of rows are about to be returned
295315 let ( columns, column_names) = self
0 commit comments