fix(protocol): handle SQL PREPARE/EXECUTE over extended protocol - #1600
dipeshbabu wants to merge 5 commits into
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
jkaczman
left a comment
There was a problem hiding this comment.
Going off memory, I think LIMIT / OFFSET won't work with this. If it's a simple-ish fix to cover that, I think it'd be great to support that here as well. If it's difficult, I suppose we could file another issue, and leave a comment in the code explaining that it's broken. I'm also curious if anything else being re-written for Prepare/Execute is affected by this.
Ref to my previous issue implementing that and where I test that general code:
pgdog/integration/rust/tests/integration/simple_prepared.rs
Lines 36 to 39 in 9d83dea
Could you also write a basic test in our Ruby / Elixir suites to ensure there's no other issues? Ruby has suites covering full/extended/disabled prepared_statements, and Postgrex is pretty strict about ensuring protocol conformity through its state machine.
|
Fixed LIMIT/OFFSET and generated-ID rewrites, including repeated executions. The Postgrex test also caught unnamed-statement reuse; that's fixed too. Added Ruby/Postgrex coverage; all 27 validation jobs pass. |
jkaczman
left a comment
There was a problem hiding this comment.
Thanks for fixing that, here's some more thoughts! There's also a couple other places I see the same kind of issues with.
jkaczman
left a comment
There was a problem hiding this comment.
Oh, and, could you please delete the TODO I mentioned in my earlier comment?
jkaczman
left a comment
There was a problem hiding this comment.
I've read the changes over, I think it generally looks good other than some minor nits.
Fixes #1403.
SQL
PREPAREsent through the extended protocol was replaced with a simple query, leaving clients waiting for ParseComplete. Preserve the original message sequence and track the inner statement when Execute completes.SQL
EXECUTEnow reparses its rewritten SQL before binding, so cached outer statements use the current LIMIT/OFFSET and generated values. The internal Parse follows any required SQL PREPARE; its ParseComplete is consumed. The original Bind name remains available for decoding results. Client-local SQL preparation plans are not shared through the AST cache.Keep the client's original unnamed Parse across executions so Postgrex can reuse it after Sync; request rewrites use a separate copy.
Regression coverage includes cross-shard and direct-shard pagination, mixed parameter positions, fresh generated IDs, separate client name registration, unnamed reuse, and error recovery. Added named/unnamed Ruby cases across full/extended/disabled modes and Postgrex protocol coverage. The pagination, generated-ID, and unnamed-statement failures were reproduced before their fixes. The new Ruby and Postgrex cases also passed in isolated local runs.
All 27 validation jobs passed before pushing this update.