๐ View Raw Release Notes (Original Developer Log)
# v8.0.0-rc.19
`@default` now means a database default, and values the client generates are written `@onCreate(...)` and `@onUpdate(...)`. Every default is stored in one form owned by its column's data type, so date, time and bytes defaults are written with tags. Clients take the contract as a typed value, can render any plan as SQL without a database, and run each ORM call as one activity that middleware and the cache can see. A column of any database type can be declared with ``Raw(sql`...`)``, and Prisma 7 schemas with `Unsupported(...)` fields now load.
The upgrade recipes for this hop: the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/) and the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). Each breaking change below names the change ids to look for in them.
## Breaking changes
- **Client generators are written `@onCreate(...)` and `@onUpdate(...)`, and `@default` means a database default.** `@default(uuid())`, `@default(cuid(2))`, `@default(ulid())` and `@default(nanoid())` are refused with `PSL_GENERATOR_IN_DEFAULT`. Write `@onCreate(uuid())` and so on instead. The app recipe ships a script that rewrites your Prisma 8 schema files. The contract does not change, so there is nothing to re-emit, sign or migrate. `@default(now())` and `@default(autoincrement())` are unchanged. `contract print` now writes generated values as `@onCreate(...)` and `@onUpdate(...)`. See `client-functions-move-from-default-to-on-create` and `contract-print-writes-generator-attributes` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30780](https://github.com/prisma/orm/pull/30780))
Before:
```prisma
model Post {
id String @id @default(uuid(7))
slug String @default(nanoid(12))
}
```
After:
```prisma
model Post {
id String @id @onCreate(uuid(7))
slug String @onCreate(nanoid(12))
}
```
- **A client takes the contract as a typed value.** The `contractJson` option and the type argument on the client call are removed from `postgres()`, `postgresServerless()`, `sqlite()`, `supabase()`, `mongo()`, `postgresStatic()`, `sqliteStatic()`, `mongoStatic()` and `mongoQuery()`. Turn the emitted JSON into a value once with `contractFromJson<Contract>(contractJson)` from the facade's `/static` entry, and pass `{ contract }`. The app recipe ships a script that moves your source files; move test files by hand. The `*OptionsWithContract` and `*OptionsWithContractJson` types are replaced by `PostgresOptions<Contract>` and the matching types of the other facades. See `client-takes-contract-value` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30748](https://github.com/prisma/orm/pull/30748))
Before:
```ts
export const db = postgres<Contract>({ contractJson, url: process.env['DATABASE_URL']! });
```
After:
```ts
import { contractFromJson } from '@prisma/orm-postgres/static';
export const contract = contractFromJson<Contract>(contractJson);
export const db = postgres({ contract, url: process.env['DATABASE_URL']! });
```
- **Date, time, interval and bytes defaults are written with tags, and each default has one stored form.** `contract emit` refuses a quoted date, time, interval or bytes default and names the tag to write. A `bytea` default takes hexadecimal, not base64. A PostgreSQL contract that stores a default in another form than its column's type gives, such as `"1.5"` on `numeric(10,2)`, is refused by the CLI: run `prisma contract emit`, then `prisma db sign`. On SQLite, datetime and JSON columns get their own data types; run the app recipe's script before the next CLI command, because the CLI refuses the old contract. Reading a value that its column's type cannot hold now throws `RUNTIME.DECODE_FAILED`. A SQLite `DateTime` text with no UTC offset is read as UTC. Run `prisma db sign` against every database after the upgrade. See `date-time-interval-and-bytes-defaults-use-tags`, `sqlite-contracts-name-datetime-and-json-data-types`, `postgres-defaults-stored-in-another-spelling`, `prisma7-datetime-default-finer-than-column`, `stored-values-a-column-type-does-not-hold`, `sqlite-datetime-without-offset-read-as-utc`, `text-array-min-max-return-arrays` and `sign-databases-after-data-type-values` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30750](https://github.com/prisma/orm/pull/30750))
Before:
```prisma
at DateTime @default("2024-01-01T00:00:00Z")
day Date @default("2024-03-15")
payload Bytes @default("AQID")
```
After:
```prisma
at DateTime @default(timestamptz`2024-01-01T00:00:00Z`)
day Date @default(date`2024-03-15`)
payload Bytes @default(bytea`\x010203`)
```
- **`@noCheck` is removed, and a list that allows null elements is written `T?[]`.** A stored contract with a `noCheck` key no longer loads. First run the app recipe's script, which rewrites stored contracts and migration snapshots, then run `prisma db sign` against every database. Then replace `T[] @noCheck(elementNotNull)` with `T?[]` and delete `@noCheck(membership)`; in TypeScript, use `.many({ elementsNullable: true })`. A contract read from a Prisma 7 schema now types list elements as `T | null`, and the Supabase extension's four `text[]` columns allow null elements; both change the storage hash, so sign your databases. See `stored-contracts-drop-nocheck`, `psl-nocheck-removed`, `ts-nocheck-method-removed`, `prisma7-lists-allow-null-elements` and `supabase-contract-lists-allow-null-elements` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). Extension authors run the same script from the extension package root, then re-emit the bundled contract; see `stored-contracts-drop-nocheck`, `psl-nocheck-removed` and `ts-nocheck-method-removed` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30741](https://github.com/prisma/orm/pull/30741))
Before:
```prisma
tags String[] @noCheck(elementNotNull)
```
After:
```prisma
tags String?[]
```
- **Type-constructor arguments are values.** A quoted number, such as `VarChar("255")` or `Timestamp("3")`, is refused with `PSL_VALUE_TYPE_INCOMPATIBLE`; write the number without quotes. On Postgres a whole number written with a fraction, such as `VarChar(255.0)`, is refused too, and so is a number the type cannot hold. The same applies to a field preset's precision, such as `temporal.timestamp("3")`. See `type-constructor-arguments-are-values` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30801](https://github.com/prisma/orm/pull/30801))
Before:
```prisma
name VarChar("255")
```
After:
```prisma
name VarChar(255)
```
- **Enum members are values of their data type.** A PSL enum member is read as a value of the enum codec's data type, as a `@default` is. A quoted member is refused on a codec whose type is not text, such as `pg/numeric@1` or `pg/int8@1`; write numbers unquoted and dates and times with their tag. Enums typed by `pg/jsonb@1`, `pg/timetz@1`, `pg/enum@1`, `arktype/json@1`, `pg/vector@1` or `pg/geometry@1` are refused; use a text enum, or a native enum instead of `pg/enum@1`. Members of a `pg/numeric@1`, `pg/interval@1` or `mongo/decimal128@1` enum compare as values, so `0.5` and `0.50` are duplicates. Columns of more enum codecs are now typed as the union of their members; re-emit the contract. See `psl-enum-members-read-by-the-cast-rule`, `more-codecs-refused-for-enums`, `enum-members-compare-by-their-data-type` and `enum-columns-typed-by-member-literals` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30790](https://github.com/prisma/orm/pull/30790))
Before:
```prisma
enum Ratio {
@@type("pg/numeric@1")
Half = "0.5"
}
```
After:
```prisma
enum Ratio {
@@type("pg/numeric@1")
Half = 0.5
}
```
- **Generator arguments are checked, and a generator must fit its column.** An argument `uuid`, `cuid` or `nanoid` does not take, such as `uuid(5)`, is now refused, in Prisma 8 PSL with `PSL_INVALID_GENERATOR_ARGUMENT` and in a Prisma 7 schema with `PSL.PRISMA7_UNKNOWN_DEFAULT`; it used to be read as something else. A number with a fraction, such as `nanoid(8.0)`, is refused too. A generator on a Postgres column too short for what it writes, such as `VarChar(5) @onCreate(uuid())`, is refused when the contract is built instead of failing at the first insert. A SQL `@@discriminator` that is not text has a new message. See `prisma7-default-function-arguments-checked`, `generator-function-argument-diagnostics`, `generator-function-argument-with-fraction`, `generator-fits-column` and `discriminator-must-be-text` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30792](https://github.com/prisma/orm/pull/30792))
- **Re-emit `contract.d.ts`, and expect more precise types from `defineContract`.** `prisma contract emit` writes field and column types as generics applied to the contract, so a SQL `contract.d.ts` emitted by an earlier release no longer compiles; re-emit it. A contract built with `defineContract` now gets the same ORM types as an emitted one: typed `include` rows, aggregates, query operations, parameterized types such as `Varchar<50>`, index names in `where` and `orderBy` callbacks, unique keys in `whereUnique`, and its enums. A Mongo `defineContract` contract types lists and value objects as `readonly`, and its factory form no longer types every field as `never`. Casts that only worked because a type was `unknown` or `never` may now fail to compile. See `typescript-contract-include-row-types`, `typescript-contract-aggregates-and-operations`, `typescript-contract-parameterized-output-types`, `typescript-contract-index-references`, `typescript-contract-storage-and-domain-types`, `typescript-contract-enums-in-domain`, `emitted-contract-types-from-generics`, `emitted-field-types-from-shared-generic`, `mongo-define-contract-readonly-rows`, `mongo-define-contract-factory-field-types`, `value-object-enum-fields-narrow` and `mongo-update-accessors-take-input-types` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30709](https://github.com/prisma/orm/pull/30709), [#30747](https://github.com/prisma/orm/pull/30747))
- **A MongoDB field keeps its schema name in code.** A field declared `id ObjectId @id @map("_id")` is the field `id` in the contract, in ORM rows and in `where`, `select`, `orderBy` and write data, where it was `_id`. The contract records the stored name in `model.storage.fields`, and a contract without it is refused with `CONTRACT.VALIDATION_FAILED`. Run `prisma contract emit`, then the app recipe's script, which rewrites migration snapshots. Storage hashes do not change. `--rename` and `--delete` name fields by their schema names. `@map` on a field of a composite type is now refused, because it was always ignored. In the TypeScript builder, set a stored name with `.mongo({ field: '_id' })`. See `mongo-contracts-record-stored-field-names`, `mongo-orm-uses-field-names`, `mongo-statements-name-fields`, `mongo-composite-field-map-refused` and `mongo-typescript-stored-field-names` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30779](https://github.com/prisma/orm/pull/30779))
Before:
```ts
await db.orm.users.where({ _id: user._id }).update({ name: 'Ada' });
```
After:
```ts
await db.orm.users.where({ id: user.id }).update({ name: 'Ada' });
```
- **MongoDB contracts written in TypeScript get a collection validator.** A `defineContract` contract now gets the same closed `$jsonSchema` validator as a PSL contract, and its storage hash changes once. `defineContract` refuses what a validator cannot describe, such as an `_id` that can hold an array or null. MongoDB does not check existing documents when a validator is added, so fix documents the validator would refuse, then apply it with `prisma db update`, or with `prisma migration plan` and `prisma db migrate`. A collection shared by several models now gets a validator that accepts each of them; apply it the same way. See `mongo-typescript-contract-validator` and `mongo-shared-collection-validator` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30773](https://github.com/prisma/orm/pull/30773))
- **Each SQL ORM call is one `orm-call` activity, and ORM annotations live on it.** The statements an ORM call sends carry no user annotations, so a middleware that reads an annotation from a statement plan finds nothing; read it in `activityStarted` from the `orm-call` activity. The cache middleware caches an annotated ORM read as a whole, keyed by `cacheAnnotation({ key })` or by the call's content hash; `deriveKey` applies only to SQL builder queries. If your `deriveKey` separates tenants or users, give each annotated ORM read a tenant-prefixed `key`, or one tenant's cached ORM read can be served to another. A custom cache store holds `CachedValue` instead of `CachedRows`. A hand-built object passed to `orm()` that copies only `query` and `execute` now fails with `ORM.ACTIVITY_SOURCE_MISSING`. An ORM call still pending at `close()` now completes instead of rejecting. See `orm-annotations-on-the-call`, `cached-orm-reads-key-on-the-call`, `cache-store-holds-cached-values`, `orm-needs-a-runtime-queryable` and `close-lets-open-orm-calls-finish` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30749](https://github.com/prisma/orm/pull/30749))
Before:
```ts
async beforeEncode(plan) {
const actor = auditAnnotation.read(plan);
if (actor) log(actor);
},
```
After:
```ts
async activityStarted(activity) {
if (activity.kind !== 'orm-call') return;
const actor = auditAnnotation.read(activity);
if (actor) log(actor);
},
```
- **Migration checks require the full effect of an operation, so plan unapplied migrations again.** The runner skips an operation only when its checks show the whole effect is already in place. On PostgreSQL, SQLite and MongoDB these checks now compare the full definition, not just a name. An `ops.json` written by an earlier release keeps its old checks: run `migration.ts` again for each migration that is not applied yet. On PostgreSQL, `this.setDefault` no longer takes `operationClass`; delete the option. Widening an `autoincrement()` column now also widens its sequence; for a migration already applied, run `ALTER SEQUENCE โฆ AS bigint` yourself. `this.alterColumnType` with `using` on a column that already has the new type is refused; write the conversion as a `dataTransform`. See `setdefault-operation-class-derived`, `setdefault-has-no-postcheck`, the `postgres-postcheck-*` entries, `postgres-alter-column-type-unchanged-refused`, `postgres-autoincrement-sequence-follows-column-type`, `sqlite-postchecks-check-full-definition` and `mongo-postchecks-check-full-definition` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30752](https://github.com/prisma/orm/pull/30752))
- **A failed migration reports the runner's own error code.** `MIGRATION.RUNNER_FAILED` no longer exists. A failed apply reports codes such as `MIGRATION.SCHEMA_VERIFY_FAILED`, `MIGRATION.PRECHECK_FAILED` or `MIGRATION.POSTCHECK_FAILED`, with typed `meta.schemaIssues` and `meta.failedCheck`. On a control client, `dbInit`, `dbUpdate` and `migrate` take a required `invocation` option, and their failures are `CliStructuredError`s. See `runner-failures-report-own-codes` and `control-client-apply-takes-invocation` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30791](https://github.com/prisma/orm/pull/30791))
- **`prisma db schema --json` names a column's type `typeText`.** It holds the type as the database reports it, such as `integer`, in place of `nativeType`, and `resolvedNativeType` is gone. The tree output shows the same text. `CONTRACT.DEFAULT_INVALID` carries `meta.typeText` instead of `meta.nativeType`. See `db-schema-json-names-type-text` and `default-invalid-meta-type-text` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30777](https://github.com/prisma/orm/pull/30777))
- **String timestamp columns are filled with text.** The Postgres `temporal.*String` presets, and every `@updatedAt` field a `prisma7Schema(...)` contract reads, now fill the column with text instead of a `Date`. Re-emit the contract; only the execution hash changes. The `pg/timestamp-string@1` and `pg/timestamptz-string@1` codecs refuse a `Date` at runtime with `RUNTIME.ENCODE_FAILED`. See `string-timestamp-presets-write-text` and `string-timestamp-codecs-take-text-only` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30742](https://github.com/prisma/orm/pull/30742))
- **`using` is a reserved member of every ORM collection.** A custom collection class with its own member named `using` no longer compiles; rename it. See `orm-collection-member-using-reserved` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30717](https://github.com/prisma/orm/pull/30717))
- **Objects that implement client or transaction types need the new members.** Clients and transactions gain `query`, `execute`, `toSql` and other members (see Features). Code that only uses these types needs no change. Code that builds its own object of one of them, such as a test double, must add the new members. `supabase()` now creates its pool on the first query. See `client-query-and-to-sql` in the [app recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/app/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/) and `transaction-query-members` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30802](https://github.com/prisma/orm/pull/30802), [#30789](https://github.com/prisma/orm/pull/30789))
- **Extension authors: activities, codecs and generator functions.** `RuntimeActivity` is renamed `Activity` and now includes client activities, which an extension starts with `startActivityOn`; queryables and transactions carry an activity source. A codec implements `toWire`, `fromWire`, `toDataTypeValue` and `fromDataTypeValue` instead of `encode`, `decode`, `encodeJson` and `decodeJson`, and a data type's `read` replaces `toCanonicalForm`. A default function can no longer generate a value in the client; contribute a generator function instead, and stop registering the identifier generators the SQL family now registers. A SQL target declares the `uuid`, `cuid` and `nanoid` signatures with `sqlIntegerArgumentGeneratorFunctions`. See `runtime-activity-is-activity`, `activity-includes-client-activities`, `start-a-client-activity`, `runtime-connections-carry-an-activity-source`, `begin-transaction-on-takes-a-parent`, `transaction-activity-takes-a-parent`, `orm-runtime-objects-carry-an-activity-source`, `orm-annotations-on-the-call`, `cache-store-holds-cached-values`, `queryable-carries-the-activity-source`, `codecs-read-wire-and-data-type-values`, `data-types-own-parameter-limits`, `json-helpers-renamed`, `stored-form-helpers-renamed`, `projections-read-by-from-wire`, `empty-result-json-renamed-empty-result-wire`, `default-functions-lower-to-database-defaults-only`, `applicable-codec-ids-and-build-phases-removed`, `sql-family-registers-identifier-generators`, `sql-target-declares-integer-argument-generators`, `generator-signature-from-data-types`, `generator-function-field-length`, `build-contract-definition-takes-lookups`, `arg-binding-spec-label`, `one-of-refuses-data-type-value` and `text-data-types` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). ([#30706](https://github.com/prisma/orm/pull/30706), [#30749](https://github.com/prisma/orm/pull/30749), [#30750](https://github.com/prisma/orm/pull/30750), [#30780](https://github.com/prisma/orm/pull/30780), [#30742](https://github.com/prisma/orm/pull/30742), [#30792](https://github.com/prisma/orm/pull/30792))
- **Extension authors: type constructors, column types, contract types and MongoDB.** A type constructor's value argument is declared `{ kind: 'value', dataType }`, and the `string`, `boolean` and `stringArray` kinds are removed. Columns are compared by data type, so the type-name normalisers and `SqlTypeLookups` and `MongoTypeLookups` are removed, schema IR columns have `typeText`, and the Postgres and SQLite control adapters take the stack's data types. A codec whose output type depends on its type parameters declares a type function instead of `renderOutputType`, and `FieldTypesFromDomain` moves to `@prisma/orm-framework/contract/types`. A MongoDB model's storage records each field's stored name, and `deriveJsonSchema` is replaced by `deriveCollectionValidators`. See `value-arguments-name-a-data-type`, `value-argument-types-in-typescript`, `psl-and-print-helpers-take-data-types`, `composed-helpers-take-no-data-type-lookup`, `helper-codec-invariants`, `type-lookups-one-framework-type`, `type-name-normalisers-removed`, `introspected-type-text`, `schema-ir-column-type-text`, `default-resolver-takes-the-column`, `alter-type-postcheck-by-data-type`, `control-adapters-take-declared-data-types`, `resolved-sql-type-carries-the-data-type`, `typescript-contract-pack-type-slots`, `parameterized-output-types-declared-once`, `psl-interpreter-contract-capabilities`, `field-types-expression-removed`, `field-types-generic-moved`, `resolve-field-value-set-renamed`, `mongo-parameterized-output-types`, `family-codec-templates-render-no-literals`, `enum-block-written-values`, `mongo-model-storage-fields`, `mongo-validator-derivation-moves-to-mongo-contract`, `mongo-derive-json-schema-replaced-by-derive-collection-validators` and `aggregate-operation-using-reserved` in the [extension recipe](https://github.com/prisma/orm/blob/v8.0.0-rc.19/skills/prisma-8/upgrading/extension/upgrades/8.0.0-rc.18-to-8.0.0-rc.19/). The app-facing changes above also apply to extensions that build clients, write migrations or ship contracts. ([#30801](https://github.com/prisma/orm/pull/30801), [#30777](https://github.com/prisma/orm/pull/30777), [#30709](https://github.com/prisma/orm/pull/30709), [#30747](https://github.com/prisma/orm/pull/30747), [#30790](https://github.com/prisma/orm/pull/30790), [#30779](https://github.com/prisma/orm/pull/30779), [#30733](https://github.com/prisma/orm/pull/30733), [#30773](https://github.com/prisma/orm/pull/30773), [#30717](https://github.com/prisma/orm/pull/30717))
## Features
- `@onCreate(fn())` and `@onUpdate(fn())` set the values the client generates, and each function resolves for the column's codec: `uuid()` works on `String`, `VarChar(n)`, `Char(n)` and `Uuid`. A column may have both a database `@default` and a generator. The TypeScript builder has `.onCreate(gen.uuid(7))` and `.onUpdate(gen.now())`. ([#30780](https://github.com/prisma/orm/pull/30780))
- Every Postgres date and time type has a `now()` generator, including `date`, `time` and `timetz`, so `@updatedAt` works on `@db.Date`, `@db.Time` and `@db.Timetz`. A generator on an optional field generates a value the client leaves out and stores an explicit `null`. ([#30742](https://github.com/prisma/orm/pull/30742))
- ``Raw(sql`ltree`)`` declares a column of a database type no data type in the stack knows, on Postgres and SQLite. Migrations create it from the text, `db verify` compares that text with the database, and the ORM reads and writes its values as `unknown`. The TypeScript builder has ``type.Raw(sql`...`)`` and ``rawColumn(sql`...`)``. ([#30745](https://github.com/prisma/orm/pull/30745), [#30801](https://github.com/prisma/orm/pull/30801))
- A Prisma 7 schema with `Unsupported(...)` fields now loads through `prisma7Schema()`. Each such field becomes a raw column with no field on the model, as in Prisma 7's client. ([#30788](https://github.com/prisma/orm/pull/30788))
- A Prisma 7 schema with `@updatedAt` beside `@default(now())`, or with a generator on an optional field, now loads, signs and verifies against the database Prisma 7 built. ([#30742](https://github.com/prisma/orm/pull/30742))
- A client can be created with no database. `db.toSql(plan)` renders any plan as `{ sql, params }`, and `db.query(plan)` and `db.execute(plan)` run a plan directly. `postgres()`, `postgresServerless()`, `sqlite()` and `supabase()` take `mode: 'strict' | 'permissive'`. ([#30802](https://github.com/prisma/orm/pull/30802))
- Every SQL client takes custom collection classes as the `collections` option, and uses them on `db.orm`, on every transaction's `tx.orm`, on serverless connections and on Supabase role-bound clients. ([#30776](https://github.com/prisma/orm/pull/30776))
- A transaction offers the client's query members (`sql`, `orm`, `raw`, `prepare`, `query`, `execute`) on every SQL client. A Supabase role-bound client gains `prepare`, and SQLite's `db.orm` gains `fragment`. ([#30789](https://github.com/prisma/orm/pull/30789))
- Packages contribute collection methods computed from a model, under `using`. The Postgres package adds a search method for each full-text index, such as `db.orm.public.Post.using.post_search(query)`, and pgvector adds a nearest-neighbour search for each vector field. The methods chain with `where`, `orderBy` and `limit`. ([#30717](https://github.com/prisma/orm/pull/30717))
- Middleware sees each SQL ORM call as one `orm-call` activity, with its statements as children, and can answer the whole call through `intercept.onActivity`. The cache middleware uses this to cache an annotated ORM read as a whole, so a cache hit sends no statement. ([#30706](https://github.com/prisma/orm/pull/30706), [#30749](https://github.com/prisma/orm/pull/30749))
- ORM filters and writes take each field's input type, so a `Varchar<50>`, `Char<36>` or `Numeric<10, 2>` field accepts a plain string in `where`, `create`, `update` and the other write methods. ([#30709](https://github.com/prisma/orm/pull/30709))
- A `pg.enum` column can name a `native_enum` declared in another namespace, such as `pg.enum(auth.OrderStatus)`. ([#30721](https://github.com/prisma/orm/pull/30721))
- `prisma contract infer` reads each column's type from the data types of the configured target and extensions. It writes the shortest matching type constructor, and when columns have types no pack declares, it fails once and lists every one of them instead of writing a schema that cannot emit. New `Bit`, `VarBit` and `Interval` type constructors let those columns infer. ([#30735](https://github.com/prisma/orm/pull/30735))
- `prisma db verify` and the migration planner compare column types as data types with their parameters, so `numeric(10)` matches `numeric(10,0)`. A database column of a type no configured pack declares gets a message that says so. ([#30777](https://github.com/prisma/orm/pull/30777))
- A SQL `@@discriminator` field may be a `Char(n)` or `VarChar(n)` column on Postgres, or a `sql.String(n)` column on SQLite. ([#30792](https://github.com/prisma/orm/pull/30792))
## Fixes
- A hand-written `setDefault` that changes an existing default is applied instead of skipped, and the runner no longer skips an operation because an object of the same name but another definition exists. ([#30752](https://github.com/prisma/orm/pull/30752))
- Widening a Postgres `autoincrement()` column from `int4` to `int8` now also widens its sequence, which used to stop at 2147483647. ([#30752](https://github.com/prisma/orm/pull/30752))
- When a raw SQL default fails the schema check because the database stores it in another form, the error shows both texts and the `sql` literal to write. ([#30740](https://github.com/prisma/orm/pull/30740))
- The MongoDB ORM's typed `where` accepts `null`, an empty list and a whole list on list fields, and `null` on a nullable field. A `null` filter on a list field matches only a null or missing list, not a list that holds a null item. ([#30769](https://github.com/prisma/orm/pull/30769))
- A MongoDB PSL contract with a composite type that contains itself now emits, where it failed with `Maximum call stack size exceeded`. ([#30733](https://github.com/prisma/orm/pull/30733))
- A MongoDB collection that stores several unrelated models gets a validator that accepts all of them, where it described only the last model. ([#30773](https://github.com/prisma/orm/pull/30773))
- An enum field inside a value object is typed by its enum's members, as an enum field of a model is. ([#30747](https://github.com/prisma/orm/pull/30747))
- The language server no longer leaves an unhandled rejection when it removes a file watcher after the editor connection has closed. ([#30787](https://github.com/prisma/orm/pull/30787))
- A cache store's `get` and `unset` take optional fields, so code that calls a store directly passes only the fields it needs, where it had to pass `undefined` for the others. `cache.invalidate` and `cacheAnnotation` accept `undefined` for their optional fields under `exactOptionalPropertyTypes`. Stores written against the old shape still fit. ([#30822](https://github.com/prisma/orm/pull/30822))