Skip to content

Fix sql(params_inline=True) not inlining subquery filter values#2116

Open
worksbyfriday wants to merge 1 commit into
tortoise:developfrom
worksbyfriday:fix-subquery-params-inline
Open

Fix sql(params_inline=True) not inlining subquery filter values#2116
worksbyfriday wants to merge 1 commit into
tortoise:developfrom
worksbyfriday:fix-subquery-params-inline

Conversation

@worksbyfriday

Copy link
Copy Markdown

Summary

Fixes #1800

Subquery.get_sql() unconditionally called get_parameterized_sql(), which creates a new Parameterizer even when the outer context expects inline values. This caused subquery filter values to be rendered as ? placeholders instead of being inlined.

The fix checks whether the SqlContext has an active parameterizer:

  • If yes (parameterized mode): use get_parameterized_sql() so values are collected into the outer query's parameterizer
  • If no (inline mode): use get_sql() so values are rendered directly

Before

query = MyModel.filter(id__in=Subquery(OtherModel.filter(field="test_value").values_list("id")))
query.sql(params_inline=True)
# SELECT ... WHERE "id" IN (SELECT "id" FROM "other_model" WHERE "field"=?)
#                                                                        ^ value missing

After

query.sql(params_inline=True)
# SELECT ... WHERE "id" IN (SELECT "id" FROM "other_model" WHERE "field"='test_value')
#                                                                        ^ value inlined

Changes

  • tortoise/expressions.py: Check ctx.parameterizer before choosing between get_sql() and get_parameterized_sql()
  • tests/test_query_api.py: Added regression test verifying subquery values are inlined

Test plan

  • New regression test passes (test_subquery_params_inline)
  • Existing subquery tests pass (test_queryset.py -k subquery)
  • Existing params_inline tests pass (test_case_when.py)
  • All query API tests pass (16 passed, 2 skipped)

When using sql(params_inline=True) on a query with Subquery filters,
the subquery's filter values were rendered as placeholders instead of
being inlined. This happened because Subquery.get_sql() unconditionally
called get_parameterized_sql(), which creates a new Parameterizer even
when the outer context expects inline values.

The fix checks whether the SqlContext has an active parameterizer:
- If yes (parameterized mode): use get_parameterized_sql() so values
  are collected into the outer query's parameterizer
- If no (inline mode): use get_sql() so values are rendered inline

Fixes tortoise#1800
@abondar

abondar commented Mar 3, 2026

Copy link
Copy Markdown
Member

@worksbyfriday please check linter

@codspeed-hq

codspeed-hq Bot commented Mar 3, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 24 untouched benchmarks


Comparing worksbyfriday:fix-subquery-params-inline (5c020c8) with develop (314273c)

Open in CodSpeed

@waketzheng

Copy link
Copy Markdown
Contributor

For Linux/Mac, run make lint to auto fix lint issue, for windows run prek run --all-files to do that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sql(params_inline=True) doesn't include filter values from subqueries

3 participants