PostgreSQL's Extended Query Protocol Support in ProxySQL - P2#5078
Merged
renecannao merged 39 commits intov3.0from Sep 15, 2025
Merged
PostgreSQL's Extended Query Protocol Support in ProxySQL - P2#5078renecannao merged 39 commits intov3.0from
renecannao merged 39 commits intov3.0from
Conversation
The PQsendQueryPrepared function transmits the sequence BIND -> DESCRIBE(PORTAL) -> EXECUTE -> SYNC. However, libpq does not indicate whether the DESCRIBE PORTAL step produces a NoData packet for commands such as INSERT, DELETE, or UPDATE. In these cases, libpq returns PGRES_COMMAND_OK, whereas SELECT statements yield PGRES_SINGLE_TUPLE or PGRES_TUPLES_OK. This update explicitly appends a NoData packet to the result in order to provide consistent behavior across query types.
… 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.
Previously, any packet received while a query was still running was considered unexpected, and the session was terminated. This often occurred with pgJDBC, which pipelines commands (e.g., sending `BEGIN` immediately followed by another statement). Now, new packets are placed in a FIFO queue and processed only after the current query finishes and its response is sent. This preserves correct ordering, prevents unnecessary session termination, and improves compatibility with connectors like pgJDBC.
PQsendQueryPrepared always emits Bind -> Describe Portal -> Execute, which led to RowDescription being included in the result set even when the client never sent a Describe message. This caused clients to receive row descriptions they did not request. Changes: - Skip including RowDescription when the client did not send Describe. - If the client explicitly sent Describe followed by Execute, continue to skip redundant execution of Describe but include RowDescription once. This ensures RowDescription is only sent when requested, aligning behavior with protocol expectations.
… released when ProxySQL shuts down or restarts.
* Removed multi_pkt from PgSQL_session
…ckend RequestEnd was applying state changes (session variable restore, rollback-to-savepoint, multiplexing toggle for temp tables/sequences) even when the query failed to execute on the backend connection. This caused internal state to diverge from the actual backend state. Fix: - Add success/failure flag to RequestEnd calls. - Restrict state-changing logic to Simple Query and Prepared Execute. - Ensure logic only runs when the query executed successfully on backend. This keeps internal state aligned with the backend connection state.
…cle is completed When a simple query arrives while extended query messages are pending, we now: - inject an implicit Sync, - process all extended query messages, - then execute the simple query, - and send ReadyForQuery only after the simple query completes.
Remove the `DESCRIBE` (statement) cache option and related cache code.
…ded to on. Added scram_iterations in ProxySQL staup parameters status, hardcoded to 4096 (SCRAM_SHA_256_DEFAULT_ITERATIONS)
…ed via options=), the connection must be destroyed instead of returned to the pool.
…ded_query_protocol_phase_2
…ded_query_protocol_phase_2
…ded_query_protocol_phase_2
…ded_query_protocol_phase_2
ProxySQL currently does not support PostgreSQL's LISTEN command. When clients attempt to use it, we now intercept the command and return an appropriate "not supported" response instead of passing it through. This behavior is implemented for both: - Simple query flow - Extended (prepared) query flow
Previously, Parse and Describe each had their own query result handling paths. This duplicated a lot of logic and also failed to handle some cases correctly—for example, Notice messages returned by the server during extended-protocol queries. Keeping these separate paths would be hard to maintain and prone to bugs. The simple-query result handling is already mature, optimized, and covers all the necessary cases. Reusing it for Parse and Describe makes behavior consistent across simple and extended query flows, while also reducing duplicate code.
Previously, deleting `PgSQL_Errors_stats` instances in TUs with only a forward declaration caused the destructor to be skipped, leaking member allocations. The fix ensures the full class definition is visible at delete sites.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Closes #5079
Closes #5080
Closes #5081
Closes #5082
Closes #5084
Closes #5089
Closes #5091
Closes #5092