fix(orm): parenthesize an inlined computed field expression - #2796
fix(orm): parenthesize an inlined computed field expression#2796evgenovalov wants to merge 1 commit into
Conversation
A computed field is inlined into larger expressions — a boolean filter renders it as `<expr> = $n` — so an implementation whose top-level node is a bare comparison produced a chained `"authorId" = $2 = $3`. Postgres rejects that as a syntax error; sqlite and mysql only parse it correctly by accident of left associativity. Wrap the implementation's expression in parens so its operator precedence stays contained. Kysely doesn't double-wrap an already parenthesized expression, so `eb.or` /`eb.and`-based and subquery implementations compile unchanged. Fixes zenstackhq#2795 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe ORM now parenthesizes computed-field expressions before embedding them in larger SQL expressions. End-to-end tests cover direct, negated, and logical boolean filters while confirming computed-field reads. ChangesComputed field filtering
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
packages/orm/src/client/crud/dialects/base-dialect.tsESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox. 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. Comment |
Fixes #2795
Motivation
A computed field is inlined into larger expressions — a boolean filter renders it as
<expr> = $n. If the implementation's top-level node is a bare comparison, the operator precedence leaks into the surrounding query:Postgres rejects the chained
=outright. SQLite and MySQL parse it left-associatively as(a = $2) = $3, which happens to be the intended semantics, so the bug is invisible there — it surfaced only on the Postgres CI matrix of #2789.Changes
BaseCrudDialect.fieldRef()wraps the implementation's expression ineb.parens()when inlining a computed field.computed-fields.test.ts(runs on every provider in the matrix): a bare-comparison field asserted throughwhere: { isMine: true }/{ isMine: false }/NOT, plus aneb.or-based field as a no-regression guard.The wrap is unconditional because Kysely skips it for an expression that is already parenthesized, so
eb.or/eb.andand subquery implementations compile byte-for-byte as before; only bare comparisons, unary operations and raw fragments change. Verified against the compiled SQL for each shape.🤖 Generated with Claude Code
Summary by CodeRabbit
NOT, andORfiltering behavior.