Commit 34ae7d6
tml-2912: PSL native scalar lists (author, migrate, infer end-to-end) (#870)
## tml-2912 — PSL native scalar lists (slice 2 of native-scalar-arrays)
Flips the implicit gate slice 1 built behind: a user can now author SQL
scalar lists in PSL (`tags String[]`) and get them **end to end** —
native Postgres array columns (`text[]`), element-wise codec round-trip,
authoring diagnostics, capability gating, and the headline `posts.tags
String[]` milestone checkpoint (project AC1).
Stacked on slice 1 (#846, merged). The load-bearing change is one line
in the interpreter — replacing the JSONB fallback with the element
descriptor + `many: true`; the rest is making the authoring layer
correct about lists.
### Dispatches
- **D1** — interpreter flip: PSL scalar lists lower to native array
storage columns (the JSONB fallback turned out to live in **3**
coordinated sites, all removed).
- **D1b** — make `StorageColumnTypes`/`StorageColumnInputTypes`
`many`-aware (the insert/select builders consume the storage maps; only
the domain maps were wrapped before).
- **D2** — reject incoherent list constructs (execution default / `@id`
/ `autoincrement` on a list) with actionable diagnostics.
- **D3** — authoring-time capability gating: a list field against a
target whose adapter doesn't report `scalarList` (SQLite) is rejected;
threads a merged `CapabilityMatrix` to the interpreter via the existing
`mergeCapabilityMatrices`.
- **D4** — element-non-null `CHECK (array_position(col, NULL) IS NULL)`
(enforce-on-all) + array-typed `@default([])`/`@default([...])`
validation; rejects a scalar default on a list.
- **D5** — end-to-end milestone (AC1 author→migrate→infer round-trip) +
element fidelity (`DateTime[]`/`Bytes[]`/`Decimal[]`) + Mongo parity
(NFR4).
### Acceptance criteria
AC1 (milestone round-trip), AC6 (FR3 diagnostics), AC8 PSL-half
(non-null-element CHECK), AC9 (array defaults), AC10 (capability
gating), AC2/NFR1 (element fidelity), NFR4 (Mongo parity), NFR2 (no
scalar regression — `fixtures:check` byte-clean). **9/9 PASS.**
### Notes for reviewers
- **Element nullability is enforce-on-all.** PSL has no `T?[]`
(element-nullable) syntax, so every PSL-authored list column carries the
non-null-element CHECK; no `elementNullable` IR flag was needed.
- **CHECK is emitted as DDL, not via ADR-156.** ADR-156 check
constraints are value-set/`IN(...)`-only and can't express
`array_position(...)`, so D4 added a small `CheckExpressionConstraint`
DDL node (`<table>_<col>_elem_not_null`).
- **Known limitation (carried to slice 3):** opt-in `--strict` verify
would false-flag the element-non-null CHECK as drift, because
introspection doesn't parse it back. Default verify is non-strict and
unaffected; the AC1 infer round-trip is clean (`text[]` → `String[]`).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added support for scalar list fields across authoring, schema
generation, migrations, and contract emission.
* Scalar lists now use native array storage where supported, with
updated typing and round-trip behavior.
* Improved check-constraint handling to support both value-set and
expression-based validations.
* **Bug Fixes**
* Fixed list default parsing, including quoted values and special
characters.
* Improved validation for unsupported list features and stricter schema
verification for array fields.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Signed-off-by: Serhii Tatarintsev <tatarintsev@prisma.io>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>1 parent 228931d commit 34ae7d6
76 files changed
Lines changed: 2196 additions & 52 deletions
File tree
- apps/telemetry-backend
- src/prisma
- test
- packages
- 1-framework
- 1-core
- config/src
- framework-components/src
- control
- exports
- 2-authoring/psl-parser/src
- 3-tooling/cli
- src/control-api
- operations
- test
- 2-mongo-family/2-authoring
- contract-psl/test
- contract-ts/test
- 2-sql
- 2-authoring
- contract-psl
- src
- test
- contract-ts
- src
- test
- 3-tooling/emitter
- src
- test
- 4-lanes/relational-core/src
- ast
- contract-free
- exports
- 3-extensions/postgres/test
- 3-targets
- 3-targets
- postgres
- src
- core
- migrations
- exports
- test
- sqlite/src/core/migrations
- 6-adapters
- postgres
- src/core
- test/migrations
- sqlite/src/core
- skills/extension-author/prisma-next-extension-upgrade/upgrades/0.14-to-0.15
- test/integration
- test
- authoring
- parity
- scalar-lists
- sql-orm-client/fixtures/scalar-lists
- generated
- value-objects
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
162 | 162 | | |
163 | 163 | | |
164 | 164 | | |
165 | | - | |
166 | | - | |
167 | | - | |
168 | | - | |
| 165 | + | |
| 166 | + | |
169 | 167 | | |
170 | 168 | | |
171 | 169 | | |
| |||
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
3 | 4 | | |
4 | 5 | | |
5 | 6 | | |
| |||
45 | 46 | | |
46 | 47 | | |
47 | 48 | | |
| 49 | + | |
48 | 50 | | |
49 | 51 | | |
50 | 52 | | |
| |||
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
| 3 | + | |
| 4 | + | |
3 | 5 | | |
4 | 6 | | |
5 | 7 | | |
| |||
62 | 64 | | |
63 | 65 | | |
64 | 66 | | |
| 67 | + | |
65 | 68 | | |
66 | 69 | | |
67 | 70 | | |
| |||
522 | 525 | | |
523 | 526 | | |
524 | 527 | | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
525 | 533 | | |
526 | 534 | | |
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
1 | 2 | | |
2 | 3 | | |
3 | 4 | | |
| |||
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| 18 | + | |
18 | 19 | | |
19 | 20 | | |
20 | 21 | | |
| |||
69 | 70 | | |
70 | 71 | | |
71 | 72 | | |
| 73 | + | |
72 | 74 | | |
73 | 75 | | |
74 | 76 | | |
75 | | - | |
| 77 | + | |
| 78 | + | |
76 | 79 | | |
77 | 80 | | |
78 | 81 | | |
| |||
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
631 | 631 | | |
632 | 632 | | |
633 | 633 | | |
| 634 | + | |
634 | 635 | | |
635 | 636 | | |
636 | 637 | | |
| |||
0 commit comments