SQL builder: no insert whose rows come from a select, so a data migration that derives rows must be raw SQL
What happened
A data migration needs to create rows from rows that already exist: INSERT INTO actor (kind, "contactId") SELECT DISTINCT 'human', "provenanceActorId" FROM ask WHERE .... The typed SQL builder cannot express it. insert takes only literal rows, so the only way to write this inside this.dataTransform is raw SQL, which is not checked against the contract.
Reproduction
Versions: @prisma/orm-postgres 8.0.0-rc.12. Checked against the source of main at d136137 (2026-09-28).
const { sql } = postgres<Contract>({ contractJson });
sql.public.actor.insert(
sql.public.ask
.select('contactId', (f) => f.provenanceActorId)
.where((f, fns) => fns.eq(f.provenanceActorKind, 'human'))
.distinct(),
);tsc fails: TS2345: Argument of type 'SelectQuery<...>' is not assignable to parameter of type 'readonly { ... }[]'.
Cause
packages/2-sql/4-lanes/sql-builder/src/types/table-proxy.ts:insert(rows: ReadonlyArray<...>)accepts literal rows only.packages/2-sql/4-lanes/relational-core/src/ast/types.ts,InsertAst: holdsrows: ReadonlyArray<Record<string, InsertValue>>. The AST has no insert whose source is a select.
What was expected
An insert whose rows come from a select over the same contract, typed so that the select's columns must match the target's columns. Column defaults the contract declares (for example @default(uuid(7))) need a decision: either the insert-from-select applies them per row in SQL, or the select must supply the column.
Why it matters
The migration guide says a data change belongs in a typed dataTransform, because migrations form a graph and only a typed transform is checked against the contract. Any migration that introduces a table derived from existing data, such as a lookup table extracted from text columns, cannot be written that way today.
Source: prisma/prisma