TML-2786: M:N slice 2 — relation filters (some/every/none) through the junction#680
TML-2786: M:N slice 2 — relation filters (some/every/none) through the junction#680tensordreams wants to merge 6 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
size-limit report 📦
|
@prisma-next/extension-author-tools
@prisma-next/mongo-runtime
@prisma-next/family-mongo
@prisma-next/sql-runtime
@prisma-next/family-sql
@prisma-next/extension-arktype-json
@prisma-next/middleware-cache
@prisma-next/mongo
@prisma-next/extension-paradedb
@prisma-next/extension-pgvector
@prisma-next/extension-postgis
@prisma-next/postgres
@prisma-next/sql-orm-client
@prisma-next/sqlite
@prisma-next/target-mongo
@prisma-next/adapter-mongo
@prisma-next/driver-mongo
@prisma-next/contract
@prisma-next/utils
@prisma-next/config
@prisma-next/errors
@prisma-next/framework-components
@prisma-next/operations
@prisma-next/ts-render
@prisma-next/contract-authoring
@prisma-next/ids
@prisma-next/psl-parser
@prisma-next/psl-printer
@prisma-next/cli
@prisma-next/cli-telemetry
@prisma-next/emitter
@prisma-next/migration-tools
prisma-next
@prisma-next/vite-plugin-contract-emit
@prisma-next/mongo-codec
@prisma-next/mongo-contract
@prisma-next/mongo-value
@prisma-next/mongo-contract-psl
@prisma-next/mongo-contract-ts
@prisma-next/mongo-emitter
@prisma-next/mongo-schema-ir
@prisma-next/mongo-query-ast
@prisma-next/mongo-orm
@prisma-next/mongo-query-builder
@prisma-next/mongo-lowering
@prisma-next/mongo-wire
@prisma-next/sql-contract
@prisma-next/sql-errors
@prisma-next/sql-operations
@prisma-next/sql-schema-ir
@prisma-next/sql-contract-psl
@prisma-next/sql-contract-ts
@prisma-next/sql-contract-emitter
@prisma-next/sql-lane-query-builder
@prisma-next/sql-relational-core
@prisma-next/sql-builder
@prisma-next/target-postgres
@prisma-next/target-sqlite
@prisma-next/adapter-postgres
@prisma-next/adapter-sqlite
@prisma-next/driver-postgres
@prisma-next/driver-sqlite
commit: |
4ee6af6 to
78affcf
Compare
92d1741 to
25a3c7e
Compare
78affcf to
e4e3004
Compare
06fc270 to
bc2d4b9
Compare
9e24a8b to
ed06084
Compare
3982e13 to
b1dadcf
Compare
ed06084 to
38bcb74
Compare
b1dadcf to
df900cd
Compare
38bcb74 to
c32cd78
Compare
df900cd to
ee44053
Compare
b7c8ede to
c73f70b
Compare
ee44053 to
65d4fe3
Compare
Filter slice: some/every/none EXISTS through the junction. 2 dispatches (filter code / integration tests). Reuses slice 1 User↔Tag fixture. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
Add some/every/none filter support for many-to-many relations, generating
correlated EXISTS/NOT EXISTS subqueries that join through the junction table.
Both correlation sides are correctly threaded:
- junction→target: JOIN junction ON junction.childColumns = target.targetColumns
- junction→parent: WHERE junction.parentColumns = parent.{localFields→columns}
(parent anchor columns resolved via resolveFieldToColumn, mirroring slice-1
read path in buildManyToManyJunctionArtifacts)
Shapes:
- some → EXISTS(SELECT 1 FROM target JOIN junction ON <j→t> WHERE <j→parent> [AND pred])
- none → NOT EXISTS(… [AND pred])
- every → NOT EXISTS(… AND NOT(pred)); vacuously true (AndExpr.true()) when no pred
Composite keys are AND-ed across all column pairs via buildPairedColumnExprs.
A hasThrough type guard narrows ResolvedModelRelation at the dispatch site,
keeping the narrowed type in buildManyToManyExistsExpr explicit without bare casts.
Unit tests cover single-key and composite-key junction shapes for all three
modes, plus AND-ed predicate variants and the vacuous-true edge case.
FK relation filter tests are unaffected.
Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
…e/every)
Add PGlite integration tests for User.tags M:N filter operators. Tests
seed users/tags/junction rows via existing runtime-helpers and assert the
exact filtered user set as whole rows (toEqual), covering:
- some: users with ≥1 matching tag; multiple users; single match
- none: users with no matching tag (including tag-less users)
- every: all tags match + vacuous case (no-tags user qualifies) +
partial-match exclusion
- empty-match edge: some/none/every against a predicate no tag satisfies
- implicit selection: one test without .select asserts full default row shape
Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
… (TML-2786) Filter slice orchestrator artifacts (filter-code dispatch took 2 rounds incl. a truncation recovery; integration-tests dispatch one round). Review log gitignored. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
…05 rebase The EXISTS-through-junction subquery built bare table sources, which no longer compiled (main dropped the raw TableSource import) and rendered unqualified SQL. Qualify the target via tableSourceForContract and the junction via the carried through.namespaceId. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
…contract helper resolveThrough now requires the contract through block to carry the junction's namespaceId; without it the relation resolves as non-M:N and the filter EXISTS tests assert the wrong shape. Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>
65d4fe3 to
bd47c00
Compare
c73f70b to
7e21c60
Compare
Slice 2 of the SQL ORM: Many-to-Many End to End project (Linear project). Filters an M:N relation through its junction.
Overview
db.orm.User.filter((u) => u.tags.some/every/none((t) => …))now emits an EXISTS / NOT EXISTS subquery that walks theUserTagjunction. PreviouslybuildJoinWhereread onlyrelation.on.localFields/targetFields, so an M:N filter produced a wrong-shape EXISTS that skipped the junction.Changes (2 commits)
f9226ccb9—model-accessor.ts:buildManyToManyExistsExprbuilds the two-sided junction correlation — junction→target (through.childColumns = target.targetColumns) and junction→parent (through.parentColumns = parent.{on.localFields resolved}, mirroring slice 1s read correlation), composite-key AND-ed. Shapes:some=EXISTS,none=NOT EXISTS,every=NOT EXISTS(… AND NOT(pred)), vacuousevery({})=AndExpr.true()(consistent with the FKeverypath). Dispatch via ahasThroughtype predicate (no bare cast). 6 AST unit tests.e65a9db43— 9 integration tests (PGlite).Integration tests (per the project standard)
Whole-row
toEqualon the filtered user set; 8/9 use explicit.select; test 6 uses implicit/default selection. Coverssome,none,every(incl. the vacuous tag-less-user-qualifies case, tested in isolation and alongside partial-match exclusion), and empty-match edges for all three operators.Why
Second of the three relation-shaped M:N consumers over slice 0s shared
throughprimitive. The filter correlation mirrors slice 1s read correlation for consistency.Scope / notes
Filter only — write (TML-2787) is the last slice. No fixture change (reuses slice 1s
User ↔ Tag+ its seed helpers). No production change in the test dispatch. Broad integration runs show pre-existing PGlite/WASM JIT flakiness (logged); the M:N filter tests pass on targeted runs.Refs: TML-2786.