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 4 commits into
Conversation
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>
|
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: |
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.