Skip to content

feat: Bind segment values as query parameters#20

Merged
khvn26 merged 2 commits into
mainfrom
fix/parameterise-literal-values
Jul 2, 2026
Merged

feat: Bind segment values as query parameters#20
khvn26 merged 2 commits into
mainfrom
fix/parameterise-literal-values

Conversation

@khvn26

@khvn26 khvn26 commented Jul 2, 2026

Copy link
Copy Markdown
Member

Contributes to Flagsmith/flagsmith#7939.

In this PR, we add an opt-in way to have the translator emit bound query parameters instead of inlining segment values as SQL literals:

  • New Binder interface. When provided to TranslateContext, value literals (string operands, IN items, regex patterns, PERCENTAGE_SPLIT and :semver salts) are recorded and replaced with a placeholder; read them off binder.params after translation. When absent, output is identical to today.
  • Placeholder syntax is pluggable per driver: PyformatParamStyle emits %(name)s (clickhouse-driver / django-clickhouse-backend), ClickHouseServerParamStyle emits {name:String} (clickhouse-connect server-side binding).
  • Binder(prefix=...) namespaces the minted names so several predicates can be merged into one query — e.g. a UNION ALL over segments — without their p0, p1, … colliding.

Only arbitrary text values are bound. Validated numerics, booleans, and the fixed hash constants stay inline: they can't carry a % and aren't an injection vector, so every bound value is a string and the {name:String} annotation stays uniform.

The public API keeps returning str | None specifically so every existing caller, the parity harness, and the assertion suite are untouched.

Add an optional Binder on TranslateContext that promotes value-bearing
literals to bound query parameters instead of inlining them, so no user
value (notably a regex `%`) reaches a driver that substitutes parameters
by %-formatting the query text. With no Binder the output is unchanged.

beep boop
@khvn26 khvn26 requested a review from a team as a code owner July 2, 2026 14:49
@khvn26 khvn26 requested review from emyller and removed request for a team July 2, 2026 14:49
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

File Coverage Missing
All files 100%

Minimum allowed coverage is 100%

Generated by 🐒 cobertura-action against 92b5049

@emyller emyller left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit upset the interface has to change — a fix is available but you need to opt-in to it. I think I understand the issue and wish we'd have one consistent way to parse, with binding, but can't recommend a better approach without a deeper investigation and a much likely wider blast radius.

Looks good enough to me. Not blocking.

@khvn26 khvn26 merged commit dc5ae0d into main Jul 2, 2026
3 checks passed
@emyller emyller deleted the fix/parameterise-literal-values branch July 2, 2026 17:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants