fix(orm): grouped where(lambda) prefixes subgroup columns with the table (GH #205) - #206
Conversation
QueryBuilder.new() returned self.connection.query() — a table-less builder — so a where(lambda q: ...) subgroup rendered its columns with an empty table prefix, e.g. AND (."role" = 'user' ...), which Postgres rejects (syntax error at "."). Carry the current table into the nested builder. Callers that want a different table (e.g. BelongsToMany's exists/join subqueries) still override it with .table(...) immediately after new(), so their behaviour is unchanged — and the model/global scopes are deliberately not copied, keeping those subqueries clean. Add regression tests for to_sql() and to_qmark() (SQL + binding order) covering the exact grouped AND/OR pattern from GH #205.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
✅ Code Review: APPROVE (posted as comment — GitHub blocks self-approval on this account)Reviewed the diff, traced every Correctness
Binding order
Deliberate NOT-copying model/global scopes — confirmed safe
Edge cases I verified manually
Tests & CI
Regression coverage matches the issue precisely. Recommend merge — holding for QA sign-off (task #1400) per PM instruction. |
Fixes #205.
Problem
A grouped
where(lambda q: ...)rendered invalid SQL — the subgroup's columns lost their table prefix:Postgres rejects
."role"withsyntax error at or near ".".Root cause
QueryBuilder.new()returnedself.connection.query()— a builder with_table = ""and no model — andwhere()builds the subgroup ascolumn(self.new()). The grammar then rendered the subgroup columns with an empty table prefix.Fix
new()now carries the current table into the nested builder:where(lambda ...)subgroup inherits the parent table, so columns render as"messages"."role"etc.BelongsToMany's exists/join subqueries) already chain.table(...)right afternew(), so their behaviour is unchanged.Tests
New regression tests in
tests/masoniteorm/sqlite/builder/test_sqlite_query_builder.pycovering the exact grouped AND/OR pattern from the issue:to_sql()→... AND ("users"."active" = '1' AND "users"."age" > '20' OR "users"."id" >= '42')to_qmark()→ correct?placeholders and binding order['Joe', 1, 20, 42]Full ORM suite (excl. live-Postgres): 723 passed, 7 skipped. The generated SQL is now valid Postgres, so the CI Postgres job exercises it end-to-end.
Real-world validation (follow-up)
The
where_rawworkaround this unblocks lives inexample/agents/app/repositories/conversation.pyon theai-package-fixbranch (not onmain), so its revert isn't part of this PR. The added regression test replicates that exact("role" = ? AND "type" = ? OR "id" >= ?)shape; once this lands andai-package-fixsyncs, that line reverts towhere(lambda q: q.where("role","user").where("type","text").or_where("id",">=",boundary)).