Commit 508b9e0
authored
TML-2794: M:N slice 5 — PSL authors many-to-many (junction → N:M + through) (#819)
**Slice 5 of the [SQL ORM: Many-to-Many End to
End](https://linear.app/prisma-company/project/sql-orm-many-to-many-end-to-end-c178df40ca3a)
project** (follow-on group). Refs TML-2794.
> **Stacked PR** — base is `tml-2790-mn-demo-examples` (#742, slice 4);
below that `tml-2787-slice-3-write` (#683) → `main`.
## Overview
PSL could not author a navigable many-to-many relation: the relation
resolver emitted only `N:1`/`1:N`, and a bare list field (`tags Tag[]`)
with no FK pair was diagnosed as `PSL_ORPHANED_BACKRELATION_LIST` —
`cardinality: 'N:M' + through` existed only via the TS contract builder.
This PR teaches the PSL interpreter **explicit-junction recognition**
(form 1, pinned at pickup): when a bare list field has a recognisable
junction model — composite `@@id([a, b])` covering exactly the FK
columns of two `N:1` relations to the two side models — the list lowers
to a navigable `N:M` relation through that junction, shape-identical to
`rel.manyToMany` output.
## Changes
- `psl-relation-resolution.ts`: junction recognition in the
previously-orphaned branch — `findJunctionFkPairs` + id-coverage gate +
`manyToManyRelationNode`; child FK must reference the target's **full
id** (set-equal), `through.childColumns` reordered to id order (the
runtime joins `childColumns[i] = targetColumns[i]` by index); decline →
existing orphaned diagnostic. Self-referential M:N disambiguated by the
list's `@relation` name (pins the parent-side FK); unnamed symmetric
lists get the ambiguity diagnostic. Surrogate-id join models are
deliberately not recognised. Direct FK matches still win (stay `1:N`).
- 10 lowering unit tests (`interpreter.relations.many-to-many.test.ts`):
both directions, composite keys, swapped-order FK references,
self-referential, diagnostic preservation, `validateContract`
round-trip.
- PSL-authored integration fixture `fixtures/mn-psl/` (`User ↔ Tag` via
`user_tags`, mirroring the TS fixture) wired into the sql-orm-client
emit pipeline so `fixtures:check` regenerates and diffs it.
- `mn-psl-parity.test.ts`: 8 integration tests proving the full M:N ORM
API (include explicit+implicit, `some`/`none`/`every`, connect,
disconnect, nested create) against the PSL-emitted contract.
## Why
The PG demo emits its contract from PSL, so it cannot show the M:N API
until PSL can author it (slice 6 is blocked on this). Form 1 was chosen
over Prisma-style implicit lists as the smallest surface that matches
the existing diagnostic's guidance; implicit lists remain a clean
follow-up.
## Scope
PSL authoring layer + fixtures/tests only. No sql-orm-client runtime
changes, no TS-builder changes, no demo changes (slice 6). Implicit-list
authoring (form 2) deliberately excluded.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Improved many-to-many backrelation lowering via explicit junction
models, including composite-key support and correct through/column
ordering.
* Enhanced FK/backrelation metadata to improve many-to-many resolution
across namespaces.
* **Bug Fixes / Improvements**
* Added richer diagnostics for orphaned, ambiguous, and invalid
many-to-many junction scenarios.
* Strengthened full SQL contract validation for N:M through
configurations (pairing, referenced column existence, and storage-type
consistency).
* **Tests**
* Added unit tests for many-to-many lowering and diagnostics.
* Added integration parity coverage for includes, filters, and nested
writes using the mn-psl fixture.
* **Documentation / Chores**
* Updated Prisma Next emit flow and refreshed mn-psl fixture typing for
UUID-style IDs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Alexey Orlenko's AI Agent <robot@aqrln.net>1 parent 524c016 commit 508b9e0
25 files changed
Lines changed: 2761 additions & 78 deletions
File tree
- packages
- 2-sql
- 1-core/contract
- src
- test
- 2-authoring/contract-psl
- src
- test
- 3-extensions/sql-orm-client
- test/fixtures/generated
- projects/sql-orm-many-to-many
- slices
- 05-psl-many-to-many-authoring
- 07-non-id-unique-junction-targets
- skills/extension-author/prisma-next-extension-upgrade/upgrades/0.14-to-0.15
- test/integration/test/sql-orm-client
- fixtures
- execution-defaulted-tags
- generated
- generated
- mn-psl
- generated
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| 40 | + | |
40 | 41 | | |
41 | 42 | | |
42 | 43 | | |
| |||
846 | 847 | | |
847 | 848 | | |
848 | 849 | | |
| 850 | + | |
849 | 851 | | |
850 | 852 | | |
| 853 | + | |
| 854 | + | |
| 855 | + | |
| 856 | + | |
| 857 | + | |
| 858 | + | |
| 859 | + | |
| 860 | + | |
| 861 | + | |
| 862 | + | |
| 863 | + | |
| 864 | + | |
| 865 | + | |
| 866 | + | |
| 867 | + | |
| 868 | + | |
| 869 | + | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
| 894 | + | |
| 895 | + | |
| 896 | + | |
| 897 | + | |
| 898 | + | |
| 899 | + | |
| 900 | + | |
| 901 | + | |
| 902 | + | |
| 903 | + | |
| 904 | + | |
| 905 | + | |
| 906 | + | |
| 907 | + | |
| 908 | + | |
| 909 | + | |
| 910 | + | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
| 965 | + | |
| 966 | + | |
| 967 | + | |
| 968 | + | |
| 969 | + | |
| 970 | + | |
| 971 | + | |
| 972 | + | |
| 973 | + | |
| 974 | + | |
| 975 | + | |
| 976 | + | |
| 977 | + | |
| 978 | + | |
| 979 | + | |
| 980 | + | |
| 981 | + | |
| 982 | + | |
| 983 | + | |
| 984 | + | |
| 985 | + | |
| 986 | + | |
| 987 | + | |
| 988 | + | |
| 989 | + | |
| 990 | + | |
| 991 | + | |
| 992 | + | |
| 993 | + | |
| 994 | + | |
| 995 | + | |
| 996 | + | |
| 997 | + | |
| 998 | + | |
| 999 | + | |
| 1000 | + | |
| 1001 | + | |
| 1002 | + | |
| 1003 | + | |
| 1004 | + | |
| 1005 | + | |
| 1006 | + | |
| 1007 | + | |
| 1008 | + | |
| 1009 | + | |
| 1010 | + | |
| 1011 | + | |
| 1012 | + | |
| 1013 | + | |
| 1014 | + | |
| 1015 | + | |
| 1016 | + | |
| 1017 | + | |
| 1018 | + | |
| 1019 | + | |
| 1020 | + | |
| 1021 | + | |
| 1022 | + | |
| 1023 | + | |
| 1024 | + | |
| 1025 | + | |
| 1026 | + | |
| 1027 | + | |
| 1028 | + | |
| 1029 | + | |
| 1030 | + | |
| 1031 | + | |
| 1032 | + | |
| 1033 | + | |
| 1034 | + | |
| 1035 | + | |
| 1036 | + | |
| 1037 | + | |
| 1038 | + | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
| 1042 | + | |
| 1043 | + | |
| 1044 | + | |
| 1045 | + | |
| 1046 | + | |
| 1047 | + | |
| 1048 | + | |
| 1049 | + | |
| 1050 | + | |
| 1051 | + | |
| 1052 | + | |
| 1053 | + | |
| 1054 | + | |
0 commit comments