Skip to content

fix(pgwire): batched queries would use incorrect bind variables#6401

Closed
nwoolmer wants to merge 5 commits intomasterfrom
nw_pg_fix
Closed

fix(pgwire): batched queries would use incorrect bind variables#6401
nwoolmer wants to merge 5 commits intomasterfrom
nw_pg_fix

Conversation

@nwoolmer
Copy link
Copy Markdown
Contributor

@nwoolmer nwoolmer commented Nov 16, 2025

WIP

Fixes #6123

A single BindVariableService was shared between all PGPipelineEntry instances managed by a PGConnectionContext.

When running batched queries, bind-execute messages would be sent in sequence. These would re-bind the BindVariableService entries and then compile each subsequent query.

Unfortunately, only after a sync message would the results be returned. The cursors all share the same BindVariableService, so only the values of the last query are applied.

The proposed fix in this PR is to dedicate an execution context and bind variable service to each entry, so it is isolated from the other queries in the batch.

To run the test:

image

Update: the fix was PoCed but it needs proper attention, there will be a superceding PR.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Nov 16, 2025

Walkthrough

Changes introduce per-entry execution context isolation in PostgreSQL wire protocol batch processing. PGPipelineEntry now maintains individual SqlExecutionContext and BindVariableService instances, while PGConnectionContext routes pipeline operations through entry-scoped contexts instead of the shared global sqlExecutionContext.

Changes

Cohort / File(s) Summary
Per-entry execution context introduction
core/src/main/java/io/questdb/cutlass/pgwire/PGPipelineEntry.java
Adds per-entry SqlExecutionContext and BindVariableService fields initialized in constructor and cleared on close. Introduces getEntryExecutionContext() getter. Replaces shared sqlExecutionContext with per-entry context in bind variable copy, select/insert/update/DDL execution, and engine.execute operations.
Execution context consumption
core/src/main/java/io/questdb/cutlass/pgwire/PGConnectionContext.java
Updates msgExecute, syncPipeline (both success and error paths), and postCompile methods to use pipelineCurrentEntry.getEntryExecutionContext() instead of shared sqlExecutionContext.

Sequence Diagram

sequenceDiagram
    participant Client
    participant PGConnectionContext
    participant PGPipelineEntry
    participant Engine

    Note over Client,Engine: Batched Queries with Bound Parameters

    Client->>PGConnectionContext: Send batch (Query 1 + params=1, Query 2 + params=2, ...)
    
    PGConnectionContext->>PGPipelineEntry: Create entry N (entryExecutionContext initialized)
    PGPipelineEntry->>PGPipelineEntry: BindVariableService created per entry
    
    PGConnectionContext->>PGPipelineEntry: msgExecute(entryExecutionContext)
    PGPipelineEntry->>Engine: execute(entryExecutionContext with params=N)
    Engine-->>PGPipelineEntry: Result for Query N
    PGPipelineEntry->>PGConnectionContext: Return result
    
    Note over PGPipelineEntry: Parameters isolated per entry
    
    alt Next entry in batch
        PGConnectionContext->>PGPipelineEntry: Create entry N+1 (fresh entryExecutionContext)
        PGPipelineEntry->>PGPipelineEntry: New BindVariableService created
        PGConnectionContext->>PGPipelineEntry: msgExecute(entryExecutionContext)
        PGPipelineEntry->>Engine: execute(entryExecutionContext with params=N+1)
        Engine-->>PGPipelineEntry: Result for Query N+1
    end
    
    PGConnectionContext->>Client: Return all results in order
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Context lifecycle verification: Ensure per-entry SqlExecutionContext and BindVariableService initialization and cleanup are thread-safe and occur at correct lifecycle points. Verify no leaks on error paths.
  • PGPipelineEntry constructor and close methods: Confirm DenyAllSecurityContext and BindVariableServiceImpl initialization align with security model and resource management patterns.
  • Call site updates in PGConnectionContext: Verify all msgExecute, msgSync, and postCompile invocations correctly route through getEntryExecutionContext() and no legacy sqlExecutionContext references remain in critical paths.
  • Batch parameter isolation semantics: Confirm that per-entry contexts properly isolate bound variables across sequential batch commands, preventing cross-entry parameter leakage.

Suggested reviewers

  • puzpuzpuz

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely identifies the main fix: batched queries incorrectly using shared bind variables instead of per-entry variables.
Linked Issues check ✅ Passed The PR successfully addresses issue #6123 by implementing per-entry execution contexts and BindVariableService isolation, which ensures each batched query retains its own bind variable values.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the batched query bind variable issue: modifications to PGConnectionContext and PGPipelineEntry align with the stated objective of isolating bind variables per entry.
Description check ✅ Passed The PR description clearly explains the issue (shared BindVariableService causing incorrect bind variables in batched queries) and the proposed solution (per-entry execution context and BindVariableService isolation).
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch nw_pg_fix

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nwoolmer
Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Nov 16, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@nwoolmer nwoolmer added Postgres Wire Issues or changes relating to Postgres wire protocol Bug Incorrect or unexpected behavior DO NOT MERGE These changes should not be merged to main branch labels Nov 17, 2025
jerrinot added a commit that referenced this pull request Nov 25, 2025
@bluestreak01 bluestreak01 deleted the nw_pg_fix branch November 26, 2025 21:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Incorrect or unexpected behavior DO NOT MERGE These changes should not be merged to main branch Postgres Wire Issues or changes relating to Postgres wire protocol

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bound parameters in batches is broken

2 participants