Skip to content

Conversation

@nadilas
Copy link
Contributor

@nadilas nadilas commented Jan 27, 2026

Ecto's query planner transforms {:type, _, [expr, type]} AST nodes into %Ecto.Query.Tagged{} structs. The SQL generator only handled the pre-planning tuple form, causing type-wrapped fragments (e.g. type(fragment(...), :integer)) to fall through to the catch-all expr clause which rendered a single '?' placeholder. This caused parameter count mismatches with Hrana/Turso.

Fixes Oban Web JobQuery.limit_query crash on '$state' jobs page.

Summary by CodeRabbit

Release Notes

  • Improvements
    • Optimised IN clause handling with subqueries to generate more efficient SQL queries.
    • Enhanced support for complex query patterns with improved type casting and subquery processing.

✏️ Tip: You can customize this high-level summary in your review settings.

The catch-all IN clause handler was wrapping SubQuery expressions in
JSON_EACH(), producing invalid SQL like:
  WHERE id IN (SELECT value FROM JSON_EACH(?))

This adds a specific pattern match for %Ecto.SubQuery{} before the
catch-all, generating proper inline subqueries:
  WHERE id IN (SELECT s0.id FROM table AS s0 WHERE ...)

Also adds a general SubQuery expression handler that properly resolves
parent query aliases and combination queries.

This fixes compatibility with libraries like Oban that use subqueries
in UPDATE...WHERE id IN (subquery) patterns.
Ecto's query planner transforms {:type, _, [expr, type]} AST nodes
into %Ecto.Query.Tagged{} structs. The SQL generator only handled
the pre-planning tuple form, causing type-wrapped fragments (e.g.
type(fragment(...), :integer)) to fall through to the catch-all
expr clause which rendered a single '?' placeholder. This caused
parameter count mismatches with Hrana/Turso.

Fixes Oban Web JobQuery.limit_query crash on completed jobs page.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 27, 2026

Walkthrough

The update modifies internal logic in the Ecto LibSQL adapter to enhance SQL generation for IN clauses, introducing dedicated handling for subqueries and tagged-value lists. It also augments type casting behaviour and expression processing, ensuring correct SQL output for more complex query scenarios. No public APIs are changed.

Changes

Cohort / File(s) Summary
IN Clause/Expression Handling
lib/ecto/adapters/libsql/connection.ex
Adds IN-clause support for subqueries and Tagged lists; introduces inline subquery and enhanced type-casting paths; expands internal expression parsing logic.

Sequence Diagram(s)

Skipped (diagram criteria not met, as only one file and no three-component interaction).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

  • Datatype fixes for lists in IN clauses #65: Modifies IN-clause handling in lib/ecto/adapters/libsql/connection.ex, specifically related to unwrapping tagged list values and JSON_EACH fallback—highly relevant overlap in logic.

Poem

A rabbit hops with keen delight,
Into SQL fields so bright—
Subqueries tucked in IN’s new tune,
Tagged lists freed to dance and swoon.
Type casts prance on syntax ground,
Internal logic newly sound—
Oh, what clever holes I’ve found!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix/tagged struct expr handling' accurately describes the main change: fixing handling of Ecto.Query.Tagged structs in expression generation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@ocean ocean merged commit d2f693c into ocean:main Jan 28, 2026
11 checks passed
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