Skip to content

TML-2786: M:N slice 2 — relation filters (some/every/none) through the junction#680

Open
tensordreams wants to merge 4 commits into
tml-2785-slice-1-correlated-readfrom
tml-2786-slice-2-filter
Open

TML-2786: M:N slice 2 — relation filters (some/every/none) through the junction#680
tensordreams wants to merge 4 commits into
tml-2785-slice-1-correlated-readfrom
tml-2786-slice-2-filter

Conversation

@tensordreams
Copy link
Copy Markdown
Contributor

Slice 2 of the SQL ORM: Many-to-Many End to End project (Linear project). Filters an M:N relation through its junction.

Stacked PR. Base is tml-2785 (#679, slice 1) → tml-2784 (#678) → tml-2597 (#673) → tml-2729 (#667) → main. Review/merge bottom-up.

Overview

db.orm.User.filter((u) => u.tags.some/every/none((t) => …)) now emits an EXISTS / NOT EXISTS subquery that walks the UserTag junction. Previously buildJoinWhere read only relation.on.localFields/targetFields, so an M:N filter produced a wrong-shape EXISTS that skipped the junction.

Changes (2 commits)

  • f9226ccb9model-accessor.ts: buildManyToManyExistsExpr builds 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)), vacuous every({})=AndExpr.true() (consistent with the FK every path). Dispatch via a hasThrough type predicate (no bare cast). 6 AST unit tests.
  • e65a9db43 — 9 integration tests (PGlite).

Integration tests (per the project standard)

Whole-row toEqual on the filtered user set; 8/9 use explicit .select; test 6 uses implicit/default selection. Covers some, 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 through primitive. 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.

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>
@tensordreams tensordreams requested a review from a team as a code owner June 1, 2026 19:41
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 1, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: e4d8d147-08c8-4973-a724-2fa4134f1322

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch tml-2786-slice-2-filter

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.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 1, 2026

size-limit report 📦

Path Size
postgres / no-emit 136.31 KB (+0.18% 🔺)
postgres / emit 125.97 KB (+0.19% 🔺)
mongo / no-emit 75.69 KB (0%)
mongo / emit 70.68 KB (0%)

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 1, 2026

Open in StackBlitz

@prisma-next/extension-author-tools

npm i https://pkg.pr.new/@prisma-next/extension-author-tools@680

@prisma-next/mongo-runtime

npm i https://pkg.pr.new/@prisma-next/mongo-runtime@680

@prisma-next/family-mongo

npm i https://pkg.pr.new/@prisma-next/family-mongo@680

@prisma-next/sql-runtime

npm i https://pkg.pr.new/@prisma-next/sql-runtime@680

@prisma-next/family-sql

npm i https://pkg.pr.new/@prisma-next/family-sql@680

@prisma-next/extension-arktype-json

npm i https://pkg.pr.new/@prisma-next/extension-arktype-json@680

@prisma-next/middleware-cache

npm i https://pkg.pr.new/@prisma-next/middleware-cache@680

@prisma-next/mongo

npm i https://pkg.pr.new/@prisma-next/mongo@680

@prisma-next/extension-paradedb

npm i https://pkg.pr.new/@prisma-next/extension-paradedb@680

@prisma-next/extension-pgvector

npm i https://pkg.pr.new/@prisma-next/extension-pgvector@680

@prisma-next/extension-postgis

npm i https://pkg.pr.new/@prisma-next/extension-postgis@680

@prisma-next/postgres

npm i https://pkg.pr.new/@prisma-next/postgres@680

@prisma-next/sql-orm-client

npm i https://pkg.pr.new/@prisma-next/sql-orm-client@680

@prisma-next/sqlite

npm i https://pkg.pr.new/@prisma-next/sqlite@680

@prisma-next/target-mongo

npm i https://pkg.pr.new/@prisma-next/target-mongo@680

@prisma-next/adapter-mongo

npm i https://pkg.pr.new/@prisma-next/adapter-mongo@680

@prisma-next/driver-mongo

npm i https://pkg.pr.new/@prisma-next/driver-mongo@680

@prisma-next/contract

npm i https://pkg.pr.new/@prisma-next/contract@680

@prisma-next/utils

npm i https://pkg.pr.new/@prisma-next/utils@680

@prisma-next/config

npm i https://pkg.pr.new/@prisma-next/config@680

@prisma-next/errors

npm i https://pkg.pr.new/@prisma-next/errors@680

@prisma-next/framework-components

npm i https://pkg.pr.new/@prisma-next/framework-components@680

@prisma-next/operations

npm i https://pkg.pr.new/@prisma-next/operations@680

@prisma-next/ts-render

npm i https://pkg.pr.new/@prisma-next/ts-render@680

@prisma-next/contract-authoring

npm i https://pkg.pr.new/@prisma-next/contract-authoring@680

@prisma-next/ids

npm i https://pkg.pr.new/@prisma-next/ids@680

@prisma-next/psl-parser

npm i https://pkg.pr.new/@prisma-next/psl-parser@680

@prisma-next/psl-printer

npm i https://pkg.pr.new/@prisma-next/psl-printer@680

@prisma-next/cli

npm i https://pkg.pr.new/@prisma-next/cli@680

@prisma-next/cli-telemetry

npm i https://pkg.pr.new/@prisma-next/cli-telemetry@680

@prisma-next/emitter

npm i https://pkg.pr.new/@prisma-next/emitter@680

@prisma-next/migration-tools

npm i https://pkg.pr.new/@prisma-next/migration-tools@680

prisma-next

npm i https://pkg.pr.new/prisma-next@680

@prisma-next/vite-plugin-contract-emit

npm i https://pkg.pr.new/@prisma-next/vite-plugin-contract-emit@680

@prisma-next/mongo-codec

npm i https://pkg.pr.new/@prisma-next/mongo-codec@680

@prisma-next/mongo-contract

npm i https://pkg.pr.new/@prisma-next/mongo-contract@680

@prisma-next/mongo-value

npm i https://pkg.pr.new/@prisma-next/mongo-value@680

@prisma-next/mongo-contract-psl

npm i https://pkg.pr.new/@prisma-next/mongo-contract-psl@680

@prisma-next/mongo-contract-ts

npm i https://pkg.pr.new/@prisma-next/mongo-contract-ts@680

@prisma-next/mongo-emitter

npm i https://pkg.pr.new/@prisma-next/mongo-emitter@680

@prisma-next/mongo-schema-ir

npm i https://pkg.pr.new/@prisma-next/mongo-schema-ir@680

@prisma-next/mongo-query-ast

npm i https://pkg.pr.new/@prisma-next/mongo-query-ast@680

@prisma-next/mongo-orm

npm i https://pkg.pr.new/@prisma-next/mongo-orm@680

@prisma-next/mongo-query-builder

npm i https://pkg.pr.new/@prisma-next/mongo-query-builder@680

@prisma-next/mongo-lowering

npm i https://pkg.pr.new/@prisma-next/mongo-lowering@680

@prisma-next/mongo-wire

npm i https://pkg.pr.new/@prisma-next/mongo-wire@680

@prisma-next/sql-contract

npm i https://pkg.pr.new/@prisma-next/sql-contract@680

@prisma-next/sql-errors

npm i https://pkg.pr.new/@prisma-next/sql-errors@680

@prisma-next/sql-operations

npm i https://pkg.pr.new/@prisma-next/sql-operations@680

@prisma-next/sql-schema-ir

npm i https://pkg.pr.new/@prisma-next/sql-schema-ir@680

@prisma-next/sql-contract-psl

npm i https://pkg.pr.new/@prisma-next/sql-contract-psl@680

@prisma-next/sql-contract-ts

npm i https://pkg.pr.new/@prisma-next/sql-contract-ts@680

@prisma-next/sql-contract-emitter

npm i https://pkg.pr.new/@prisma-next/sql-contract-emitter@680

@prisma-next/sql-lane-query-builder

npm i https://pkg.pr.new/@prisma-next/sql-lane-query-builder@680

@prisma-next/sql-relational-core

npm i https://pkg.pr.new/@prisma-next/sql-relational-core@680

@prisma-next/sql-builder

npm i https://pkg.pr.new/@prisma-next/sql-builder@680

@prisma-next/target-postgres

npm i https://pkg.pr.new/@prisma-next/target-postgres@680

@prisma-next/target-sqlite

npm i https://pkg.pr.new/@prisma-next/target-sqlite@680

@prisma-next/adapter-postgres

npm i https://pkg.pr.new/@prisma-next/adapter-postgres@680

@prisma-next/adapter-sqlite

npm i https://pkg.pr.new/@prisma-next/adapter-sqlite@680

@prisma-next/driver-postgres

npm i https://pkg.pr.new/@prisma-next/driver-postgres@680

@prisma-next/driver-sqlite

npm i https://pkg.pr.new/@prisma-next/driver-sqlite@680

commit: 92d1741

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.

1 participant