From fff2a913814d9dce58ef8815418b60c5bae2dc58 Mon Sep 17 00:00:00 2001 From: Rahim Kanji Date: Fri, 22 Aug 2025 15:22:58 +0500 Subject: [PATCH] Fix omission of ReadyForQuery after error with pending extended-query messages In extended query mode, ReadyForQuery is normally deferred when there are pending messages in the queue; it is sent only after the entire extended query frame has been processed. Edge case: if a message fails with an error while the queue still contains pending messages, the queue is cleared later in the session and those pending messages are discarded. In that case, ReadyForQuery would never be sent. Change: when a result indicates an error, send ReadyForQuery immediately. The extended-query flag will still be reset later in the session. This ensures ReadyForQuery is always emitted and prevents clients from waiting indefinitely. --- lib/PgSQL_Connection.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/PgSQL_Connection.cpp b/lib/PgSQL_Connection.cpp index 51a250828..697915d82 100644 --- a/lib/PgSQL_Connection.cpp +++ b/lib/PgSQL_Connection.cpp @@ -633,8 +633,19 @@ handler_again: query_result->add_error(NULL); } + // Normally, ReadyForQuery is not sent immediately if we are in extended query mode + // and there are pending messages in the queue, as it will be sent once the entire + // extended query frame has been processed. + // + // Edge case: if a message fails with an error while the queue still contains pending + // messages, the queue will be cleared later in the session. In this situation, + // ReadyForQuery would never be sent because the pending messages are discarded. + // + // Fix: if the result indicates an error, explicitly send ReadyForQuery immediately. + // The extended query flag will still be reset later in the session. if (fetch_result_end_st == ASYNC_STMT_EXECUTE_END && - !myds->sess->is_extended_query_frame_empty()) { + !myds->sess->is_extended_query_frame_empty() && + ((query_result->get_result_packet_type() & PGSQL_QUERY_RESULT_ERROR) == 0)) { // Skip sending ReadyForQuery if there are still extended query messages pending in the queue NEXT_IMMEDIATE(fetch_result_end_st); }