A native enum column is not textual: text operations stop accepting it, and a conformance test enforces the trait - #30390
Conversation
A codec that declares the textual trait gets like, ilike, the full-text operations, the tsquery parsers' text argument and @@fullTextIndex. All of them pass the column where Postgres expects text. The new testkit suite reads the textual codecs off the descriptors and checks that Postgres accepts each one's column in ILIKE, to_tsvector, websearch_to_tsquery and a to_tsvector GIN index. It fails on pg/enum@1 at this commit: Postgres has no ILIKE or to_tsvector for an enum type. A second test runs the same checks on a native enum column and requires all four to be refused, so the checks can fail. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
pg/enum@1 declared the textual trait, so like, ilike, the full-text operations, the tsquery parsers and @@fullTextIndex all accepted a native enum column. Postgres has no LIKE, ILIKE or to_tsvector for an enum type, so every one of them typechecked and then failed in the database. The codec now declares equality and order only, and the textual conformance suite passes. min and max over a native enum used to resolve through the textual fallback. The target now lists pg/enum@1 among the codecs whose min/max preserve the input, so they still resolve to the enum codec and the emitted aggregate types do not change. Type tests cover the ORM field surface, the SQL builder fns and parsers, and min/max over the enum-order-by fixture's native enum column. @@fullTextIndex and fullTextIndex on a native enum column are refused. Upgrade fragments describe the change for apps and extensions, and ADR 203 says what textual promises. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io>
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: prisma/orm/.coderabbit.yml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (15)
Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review. 📝 WalkthroughWalkthroughPostgreSQL native enum codecs now advertise equality and order, but not textual. Text-dependent operations and full-text indexes reject native enums. Explicit min/max resolution preserves enum output. The changes also add PostgreSQL conformance tests and upgrade instructions. ChangesNative enum text-operation support
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Suggested reviewers: Merge Risk: ⚪ Minimal · up to Native enums now reject unsupported text operations while retaining comparisons and min/max. No identified issue prevents merging after normal checks. 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 12 files. (3 skipped: 3 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Comment |
@prisma/orm-extension-arktype-json
@prisma/orm-extension-middleware-cache
@prisma/orm-extension-paradedb
@prisma/orm-extension-pgvector
@prisma/orm-extension-postgis
@prisma/orm-extension-supabase
@prisma/orm-family-mongo
@prisma/orm-family-sql
@prisma/orm-framework
@prisma/orm-mongo
@prisma/orm-postgres
@prisma/orm-sqlite
@prisma/orm-target-mongo
@prisma/orm-target-postgres
@prisma/orm-target-sqlite
@prisma/orm-toolchain
commit: |
size-limit report 📦
|
Brings in main through fc35fca: multi-file PSL emission (#30379), the orm config section declared once as a schema (#30372), two migration-graph fixes, and a native enum column no longer counting as textual (#30390). Multi-file emission lands on our ground without touching it. Of the four psl-parser files it changes, none is binder.ts, entity-reference.ts, scope-chain.ts or symbol-table.ts: it adds a directive predicate, turns the interpreters plural (documents for document), and gives PslSources a merge that unions registries. A symbol table built from several documents was already the binder contract - the multiple-documents and namespace-reopened-across-documents pins covered it - so the two compose. Conflicts resolved: - psl-parser exports: both sides added an export beside the other, so both are kept, main schema-directive ahead of our scope-chain. - sql interpreter: main restructured the opening, replacing the missing target and scalar-descriptor diagnostics with assertions and deriving source from an anchor document out of the plural input. Took that opening whole and re-seated our binder construction after the collector it needs, which also lets the uncomposed-namespace filter read the target directly now that a missing one throws. Signed-off-by: Steven McClankerton <tatarintsev@prisma.io>
## Release: 8.0.0-rc.11 → 8.0.0-rc.12 This is the release PR described in [docs/oss/versioning.md](https://github.com/prisma/orm/blob/main/docs/oss/versioning.md). It bumps every workspace package to 8.0.0-rc.12 and moves the Prisma dependencies to their latest versions. **Merging this PR ships the release.** The push to `main` carries the new root `version`. The `Publish to npm` workflow then publishes 8.0.0-rc.12 under `latest` and creates a pre-release GitHub Release from the notes file. ## Review these first - [docs/releases/v8.0.0-rc.12.md](https://github.com/prisma/orm/blob/release/8.0.0-rc.12/docs/releases/v8.0.0-rc.12.md): the release notes, which become the GitHub Release body. The same entry is at the top of `CHANGELOG.md`. - The upgrade guides for [apps](https://github.com/prisma/orm/blob/release/8.0.0-rc.12/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.11-to-8.0.0-rc.12/instructions.md) and [extensions](https://github.com/prisma/orm/blob/release/8.0.0-rc.12/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.11-to-8.0.0-rc.12/instructions.md). They merge the 24 pending fragments. The original fragments are moved unchanged to `upgrade-instructions/releases/8.0.0-rc.11-to-8.0.0-rc.12/sources/`. - Four guide entries have no fragment behind them. The `migration new` default and its removed error codes (prisma#30389) had no guide entry. Neither did the PSL parser API changes (prisma#30312, prisma#30344, prisma#30335, prisma#30379). I wrote those entries while preparing the release. - Where fragments contradicted later code, the guide follows the code. Examples: the Supabase storage hash, `voidParamsSchema`, and quoted defaults printed by `infer`. ## Dependency updates | Package | From | To | Where | | --- | --- | --- | --- | | `@prisma/cli-engine` | 0.4.0 | 0.6.1 | examples, test fixtures, apps (the toolchain packages were already on 0.6.1 from prisma#30372) | | `@prisma/dev` | 0.25.1 | 0.25.2 | the workspace catalog | | `@prisma/compute-sdk` | ^0.39.0 | ^0.43.0 | `apps/telemetry-backend` | | `@prisma/management-api-sdk` | ^1.56.0 | ^1.76.0 | `apps/telemetry-backend` | compute-sdk 0.43 renames "service" to "app" and "version" to "deployment". The telemetry deploy script now uses the new names. Both SDK versions call `/v1/apps/{appId}`, so the ID stored in the existing `TELEMETRY_DEPLOY_SERVICE_ID` secret is still correct. The app's typecheck now includes `scripts/`, so it catches the next SDK rename. The repo does not depend on `@prisma/composer`. ## Fixes needed to publish - **The publish workflow has failed on `main` since prisma#30372.** `check:conformance` called the `orm` config validator as `validate(value)`. Engine 0.6 always calls `validate(value, provenance)`, and the validator reads `provenance.files`, so it threw on every input. The check now passes the same provenance the engine would. The prisma-cli copy of this check already does this. - `set-version` rewrote `workspace:@internal/cli@<version>` to `workspace:<version>`, dropping the alias. The prisma7-adoption example uses that alias. This is the first bump since the alias was added. - `lint:legacy-name` and the `add-model-map` test pointed at the pending fragment paths. They now point at the archived sources. ## Verification Passed locally: - `pnpm build` - `pnpm typecheck` - `pnpm lint` - `pnpm test:scripts` (563 tests) - `pnpm check:conformance` - `pnpm check:publish-deps` - `pnpm check:upgrade-coverage`, in both publish and PR mode - `pnpm check:release-notes`, in both publish and PR mode - `pnpm lint:legacy-name` - `pnpm lint:skills` - `pnpm test:packages`: all 18,196 tests passed Not covered locally, left to CI: - Three `test:packages` suites install packed tarballs from the registry. This machine's pnpm refuses `@vercel/detect-agent@1.2.5` because it has no provenance. CI passed the same suites on prisma#30390. - `prisma-8-cloudflare-worker` needs a local Hyperdrive database. - The telemetry backend tests need Node 24.16 with `Temporal`. This machine has 24.13. - `fixtures:check` needs Postgres. 🤖 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 PostgreSQL full-text search, multi-file schemas, prepared ORM reads and aggregates, and conflict-skipping options for bulk creation. * Added support for using a Prisma 7 schema as the contract source, JavaScript `Date` timestamps on PostgreSQL, editor support for attribute arguments, and per-finding diagnostics. * **Breaking Changes** * Prisma 8 schema files now require `// use prisma-8` on the first line; unmapped models use their names verbatim for table names. * Replace `dbgenerated(...)` with SQL tagged literals. Defaults must be valid for their column types, creation timestamps use the application clock, and native PostgreSQL enums no longer support text operations. * Config naming and path resolution, migration starting points, and extension contracts have changed. * **Bug Fixes** * Improved migration checks and branching warnings, contract generation and inference, default verification, and type checking. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Signed-off-by: willbot <w.a.madden+machine@gmail.com> Signed-off-by: Will Madden <madden@prisma.io> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Linked issue
n/a — no Linear ticket. Follow-up recorded in #30386.
Skill update
n/a — the skill reference never described native enums as text-searchable. The pending upgrade fragment
native-enum-not-textualtells app and extension authors what changed.At a glance
Decision
The native Postgres enum codec
pg/enum@1no longer declares thetextualtrait. A codec's traits are its claim about what the database type supports, and Postgres has noLIKE,ILIKE,to_tsvector, or text-search parser for an enum type. Solike,ilike, the three full-text operations, the tsquery parsers, and@@fullTextIndexstop accepting native enum columns, turning a runtime failure into a compile error. No operation special-cases enums; each one follows the corrected trait.A new conformance test in the Postgres codec testkit enforces what
textualmeans: for every built-in codec that declares it, Postgres must accept the column inILIKE,to_tsvector,websearch_to_tsquery, and ato_tsvectorGIN index. A future codec that misdeclares the trait fails that test.Reviewer notes
enumblock with@@type("pg/text@1")is stored as text and keeps every text operation.min/maxover native enums still work. They used to come through thetextualrule in the aggregate table; the enum codec now joins the existing per-codecmin/maxlist beside the temporal types. Derivingmin/maxfromorderwould claim codecs Postgres has nomin/maxfor, as the list's own comment explains.pg/enum@1in all four checks with SQLSTATE42883, then passes with the fix. A negative control keeps it able to fail: it asserts an enum column is refused in all four places.to_tsvector(col::text)runs, but Postgres refuses to index it because the enum-to-text conversion is not immutable.textualno longer attaches to native enum columns; the extension fragment says so.Behavior changes & evidence
like,ilike,fullTextMatches,fullTextRank,fullTextHeadline, and parser input; they keepeq,in, ordering, andmin/max. Implementation: codecs.ts, aggregates.ts. Evidence: native-enum-operations.test-d.ts, full-text.test-d.ts.@@fullTextIndex/fullTextIndexon a native enum column is refused when the contract is built (PSL_FULL_TEXT_INDEX_TEXT_FIELD,CONTRACT.INDEX_INVALID).textualcodec is checked against a live Postgres. Evidence: textual-trait-conformance.integration.test.ts.Testing performed
test/integrationsql-builder,sql-orm-client,enum-order-by: 1015 tests.pnpm build,pnpm typecheck:packages --concurrency=1, examples typecheck,pnpm lint;lint:castsandlint:throwsunchanged.pnpm fixtures:check,pnpm check:error-reference,pnpm check:upgrade-coverage --mode pr --prev main --head HEAD.Alternatives considered
::textcast that text operations lower through. Rejected: it needs a second capability for "indexable as text", since the cast cannot be indexed, and its only benefit is pattern or full-text search over a small fixed set of labels, where equality is the right tool.textualoperation was broken on enums, not just full-text search.Checklist
git commit -s) per the DCO.TML-NNNN: <sentence-case title>form — no ticket.Notes for the reviewer
See Reviewer notes above.
🤖 Generated with Claude Code
Summary by CodeRabbit
minandmaxcontinue to preserve native enum values and their type.textualtrait represents.