feat: add @generated attribute for stored generated columns (PostgreSQL)#5800
feat: add @generated attribute for stored generated columns (PostgreSQL)#5800bilby91 wants to merge 11 commits intoprisma:mainfrom
Conversation
Add support for PostgreSQL stored generated (computed) columns via a new @generated("sql_expr") schema attribute. Generated columns are excluded from CreateInput/UpdateInput, readable in queries, and usable in orderBy. - PSL: parse @generated("expr"), validate against @default/@id/@updatedAt/lists - Query compiler: exclude generated fields from create/update input types - DMMF: set isGenerated=true, isReadOnly=true - DDL: render GENERATED ALWAYS AS (expr) STORED - Diffing: GenerationExpression change triggers DropAndRecreateColumn - Introspection: read attgenerated from pg_attribute, render @generated on db pull Closes prisma/prisma#6336 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Gate @generated behind previewFeatures = ["generatedColumns"] - Add validation error when feature flag is missing - Add migration tests: add/remove/change generated columns on existing tables - All tests verify idempotency (no drift on re-push) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds support for generated (computed) columns via a new Changes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Pull request overview
Adds PostgreSQL support for stored generated (computed) columns via a new @generated("sql_expr") attribute (behind the generatedColumns preview feature), flowing through PSL parsing/validation, migration diffing + DDL rendering, introspection round-tripping, and Prisma Client/DMMF read-only semantics.
Changes:
- Introduces
@generated("...")in PSL with preview-feature gating and validations, and exposes generated-column metadata through walkers/DMMF/query compiler. - Implements Postgres DDL rendering (
GENERATED ALWAYS AS (...) STORED) and introspection/describer support to read/write the generation expression. - Extends schema diffing/migration logic with a
GenerationExpressionchange kind and drop+recreate strategy for generated column transitions.
Reviewed changes
Copilot reviewed 34 out of 34 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| schema-engine/sql-schema-describer/src/walkers/column/table_column.rs | Exposes generation expression on table column walkers. |
| schema-engine/sql-schema-describer/src/walkers/column.rs | Exposes generation expression on generic column walkers. |
| schema-engine/sql-schema-describer/src/sqlite.rs | Initializes new column field for SQLite describer output. |
| schema-engine/sql-schema-describer/src/postgres.rs | Reads generated-column marker + expression during Postgres schema describing. |
| schema-engine/sql-schema-describer/src/mysql.rs | Initializes new column field for MySQL describer output. |
| schema-engine/sql-schema-describer/src/mssql.rs | Initializes new column field for MSSQL describer output. |
| schema-engine/sql-schema-describer/src/lib.rs | Adds generation_expression to the schema describer Column model. |
| schema-engine/sql-migration-tests/tests/single_migration_tests/postgres/generated_column.prisma | Adds migration test fixture asserting generated-column DDL rendering. |
| schema-engine/sql-migration-tests/tests/migrations/postgres.rs | Adds Postgres migration e2e tests for add/remove/convert generated columns. |
| schema-engine/datamodel-renderer/src/datamodel/field.rs | Renders @generated("...") during datamodel rendering (e.g. db pull output). |
| schema-engine/connectors/sql-schema-connector/src/sql_schema_differ/column.rs | Adds GenerationExpression column-change kind and detection logic. |
| schema-engine/connectors/sql-schema-connector/src/sql_schema_differ.rs | Forces drop+recreate for generated-column changes. |
| schema-engine/connectors/sql-schema-connector/src/sql_schema_calculator.rs | Propagates generation expression from PSL into calculated SQL schema columns. |
| schema-engine/connectors/sql-schema-connector/src/sql_migration.rs | Improves migration-step rendering to mention generation-expression changes. |
| schema-engine/connectors/sql-schema-connector/src/introspection/rendering/scalar_field.rs | Emits @generated("...") when introspecting generated columns. |
| schema-engine/connectors/sql-schema-connector/src/introspection/introspection_pair/scalar_field.rs | Exposes generation expression on introspection scalar-field pairs. |
| schema-engine/connectors/sql-schema-connector/src/flavour/postgres/renderer.rs | Renders generated-column DDL and guards alter-column paths. |
| query-compiler/schema/src/build/mutations/create_one.rs | Excludes generated columns from checked create inputs. |
| query-compiler/schema/src/build/input_types/objects/update_one_objects.rs | Excludes generated columns from checked update inputs. |
| query-compiler/query-structure/src/field/scalar.rs | Adds is_generated_column() query-structure helper. |
| query-compiler/dmmf/src/tests/tests.rs | Adds DMMF test for read-only + excluded-from-inputs behavior. |
| query-compiler/dmmf/src/tests/test-schemas/postgres_generated_column.prisma | Adds schema fixture for DMMF generated-column test. |
| query-compiler/dmmf/src/ast_builders/datamodel_ast_builder.rs | Sets isReadOnly/isGenerated for generated columns in DMMF. |
| psl/psl/tests/common/asserts.rs | Adds assertion helper for generated-column fields in PSL tests. |
| psl/psl/tests/attributes/mod.rs | Registers generated attribute test modules. |
| psl/psl/tests/attributes/generated_positive.rs | Adds positive PSL parsing tests for @generated. |
| psl/psl/tests/attributes/generated_negative.rs | Adds negative PSL parsing/validation tests for @generated. |
| psl/psl-core/src/validate/validation_pipeline/validations/fields.rs | Adds preview-feature gating validation for generated columns. |
| psl/psl-core/src/validate/validation_pipeline/validations.rs | Wires generated-column validation into the pipeline. |
| psl/psl-core/src/common/preview_features.rs | Introduces GeneratedColumns preview feature flag + activation. |
| psl/parser-database/src/walkers/scalar_field.rs | Exposes generated-column flags + expression in parser DB walkers. |
| psl/parser-database/src/types.rs | Stores generated-column flags/expression in scalar field metadata. |
| psl/parser-database/src/attributes.rs | Parses @generated("...") and enforces cross-attribute constraints. |
| libs/sql-ddl/src/postgres.rs | Adds SQL-DDL support for rendering generated columns and tests it. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
schema-engine/connectors/sql-schema-connector/src/sql_schema_differ/column.rs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
query-compiler/schema/src/build/mutations/create_one.rs (1)
157-160:⚠️ Potential issue | 🟠 MajorUnchecked create inputs should exclude generated columns.
The
filter_unchecked_create_fieldsfunction does not exclude generated columns, which is inconsistent withfilter_checked_create_fields(line 120) that explicitly filters them out. Since generated columns are computed by the database and cannot be written to, they should be excluded from unchecked inputs to prevent users from attempting invalid writes that would fail at the database level.Proposed fix
model.fields().filter_all(move |field| match field { // In principle, all scalars are writable for unchecked inputs. However, it still doesn't make any sense to be able to write the scalars that // link the model to the parent record in case of a nested unchecked create, as this would introduce complexities we don't want to deal with right now. - ModelField::Scalar(sf) => !linking_fields.contains(sf), + // Generated (computed) columns are also excluded since they cannot be written to. + ModelField::Scalar(sf) => !linking_fields.contains(sf) && !sf.is_generated_column(),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@query-compiler/schema/src/build/mutations/create_one.rs` around lines 157 - 160, filter_unchecked_create_fields currently allows generated scalar columns through unchecked inputs; update the ModelField::Scalar branch inside filter_unchecked_create_fields (the closure where you check !linking_fields.contains(sf)) to also exclude generated columns like filter_checked_create_fields does. Concretely, add the generated-column guard (e.g., check sf.is_generated()/sf.is_generated) alongside the existing linking_fields check so generated scalar fields are filtered out for unchecked creates.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@psl/parser-database/src/attributes.rs`:
- Around line 304-333: The code currently only checks the preview feature for
`@generated`; add a connector-specific rejection so `@generated` is permitted only
for Postgres. In the validate_generated_column path (the function
validate_generated_column in
psl-core/src/validate/validation_pipeline/validations/fields.rs or the
cross-attribute block that references
ctx.types[scalar_field_id].is_generated_column), inspect the datasource provider
(e.g., ctx.datasource_provider or similar on ctx) and if it's not
Provider::Postgres produce a DatamodelError::new_attribute_validation_error
using the same "generated" attribute name and ast_field.span(), mirroring the
style of validate_scalar_field_connector_specific used for Json/Decimal types to
return a clear error for unsupported connectors. Ensure the new check runs
before migration-time assumptions (i.e., alongside the existing preview-feature
guard).
In `@psl/psl/tests/attributes/generated_negative.rs`:
- Around line 19-31: The test should_fail_without_expression_argument currently
only checks that the parse error mentions "@generated"; update it to assert the
error specifically indicates the missing expression argument for `@generated`
(e.g., check for a substring like "missing expression" or "expects an argument"
referencing "@generated") by tightening the assertion on the `error` returned
from `parse_unwrap_err(&with_header(dml, Provider::Postgres,
&["generatedColumns"]))` so the test fails if a different `@generated-related`
error occurs.
- Around line 33-45: The test should_fail_with_non_string_argument only asserts
error.contains("@generated"); update it to also assert the error message
mentions a non-string argument (e.g., contains "string" or "expected a string")
so the failure clearly targets argument type; locate the test function
should_fail_with_non_string_argument and add an assertion after
parse_unwrap_err(...) such as assert!(error.contains("string") ||
error.contains("expected a string")) referencing the existing parse_unwrap_err,
with_header, Provider::Postgres and "generatedColumns" usage to ensure the error
relates to the argument type.
In `@psl/psl/tests/attributes/mod.rs`:
- Around line 27-28: The two new module declarations "generated_positive" and
"generated_negative" should be placed in alphabetical order with the other
modules; move them so they appear after the existing "field_name_clash" module
and before "id_negative" to maintain consistent alphabetical ordering in this
file (look for the mod declarations and reorder the lines for generated_positive
and generated_negative accordingly).
In `@query-compiler/schema/src/build/input_types/objects/update_one_objects.rs`:
- Line 84: filter_unchecked_update_fields() currently allows generated scalar
fields into UncheckedUpdateInput; add the same generated-column exclusion used
elsewhere by ensuring the predicate includes !sf.is_generated_column()
(alongside existing checks like !sf.is_read_only(), is_not_autoinc, and
is_not_disallowed_id) so generated columns are omitted from UncheckedUpdateInput
and illegal writes are prevented.
In `@schema-engine/connectors/sql-schema-connector/src/sql_schema_calculator.rs`:
- Line 537: The code currently hardcodes generation_expression: None which drops
`@generated`(...) text for unsupported generated columns; update the branch in
sql_schema_calculator.rs so generation_expression is set from the source column
metadata instead of None (e.g., use the Column/ColumnWalker method that returns
the original generation expression or the stored string) so unsupported
generated columns round-trip; in short, replace the hardcoded None with the
actual generation expression retrieved from the column walker/metadata (falling
back to None only if that retrieval yields no value).
In
`@schema-engine/connectors/sql-schema-connector/src/sql_schema_differ/column.rs`:
- Around line 31-39: The match in column.rs only sets
ColumnChange::GenerationExpression when generated-ness toggles, ignoring cases
where both cols.previous.generation_expression() and
cols.next.generation_expression() are Some but different; update the match to
also detect differing expression text (or normalized forms) when both are Some
and either set ColumnChange::GenerationExpression or emit a warning/diagnostic
so schema changes that alter the expression are surfaced; use the existing
ColumnChange::GenerationExpression symbol and the
cols.previous.generation_expression()/cols.next.generation_expression()
accessors to implement the comparison (optionally normalize both expressions
before comparing) and ensure a clear message is produced when they differ.
In `@schema-engine/sql-schema-describer/src/postgres.rs`:
- Around line 865-868: Remove the duplicated comment explaining attgenerated =
's' and keep a single, concise explainers just above the is_generated_stored
assignment; update the comment near let is_generated_stored =
col.get_string("attgenerated").as_deref() == Some("s") to a single line that
mentions stored generated columns and the cast-to-text rationale (and delete the
repeated line).
---
Outside diff comments:
In `@query-compiler/schema/src/build/mutations/create_one.rs`:
- Around line 157-160: filter_unchecked_create_fields currently allows generated
scalar columns through unchecked inputs; update the ModelField::Scalar branch
inside filter_unchecked_create_fields (the closure where you check
!linking_fields.contains(sf)) to also exclude generated columns like
filter_checked_create_fields does. Concretely, add the generated-column guard
(e.g., check sf.is_generated()/sf.is_generated) alongside the existing
linking_fields check so generated scalar fields are filtered out for unchecked
creates.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 95910840-320f-422f-b551-62ea0ff3ada1
📒 Files selected for processing (34)
libs/sql-ddl/src/postgres.rspsl/parser-database/src/attributes.rspsl/parser-database/src/types.rspsl/parser-database/src/walkers/scalar_field.rspsl/psl-core/src/common/preview_features.rspsl/psl-core/src/validate/validation_pipeline/validations.rspsl/psl-core/src/validate/validation_pipeline/validations/fields.rspsl/psl/tests/attributes/generated_negative.rspsl/psl/tests/attributes/generated_positive.rspsl/psl/tests/attributes/mod.rspsl/psl/tests/common/asserts.rsquery-compiler/dmmf/src/ast_builders/datamodel_ast_builder.rsquery-compiler/dmmf/src/tests/test-schemas/postgres_generated_column.prismaquery-compiler/dmmf/src/tests/tests.rsquery-compiler/query-structure/src/field/scalar.rsquery-compiler/schema/src/build/input_types/objects/update_one_objects.rsquery-compiler/schema/src/build/mutations/create_one.rsschema-engine/connectors/sql-schema-connector/src/flavour/postgres/renderer.rsschema-engine/connectors/sql-schema-connector/src/introspection/introspection_pair/scalar_field.rsschema-engine/connectors/sql-schema-connector/src/introspection/rendering/scalar_field.rsschema-engine/connectors/sql-schema-connector/src/sql_migration.rsschema-engine/connectors/sql-schema-connector/src/sql_schema_calculator.rsschema-engine/connectors/sql-schema-connector/src/sql_schema_differ.rsschema-engine/connectors/sql-schema-connector/src/sql_schema_differ/column.rsschema-engine/datamodel-renderer/src/datamodel/field.rsschema-engine/sql-migration-tests/tests/migrations/postgres.rsschema-engine/sql-migration-tests/tests/single_migration_tests/postgres/generated_column.prismaschema-engine/sql-schema-describer/src/lib.rsschema-engine/sql-schema-describer/src/mssql.rsschema-engine/sql-schema-describer/src/mysql.rsschema-engine/sql-schema-describer/src/postgres.rsschema-engine/sql-schema-describer/src/sqlite.rsschema-engine/sql-schema-describer/src/walkers/column.rsschema-engine/sql-schema-describer/src/walkers/column/table_column.rs
query-compiler/schema/src/build/input_types/objects/update_one_objects.rs
Show resolved
Hide resolved
schema-engine/connectors/sql-schema-connector/src/sql_schema_calculator.rs
Outdated
Show resolved
Hide resolved
schema-engine/connectors/sql-schema-connector/src/sql_schema_differ/column.rs
Outdated
Show resolved
Hide resolved
- Gate att.attgenerated query behind SupportsGeneratedColumns circumstance flag (PG 12+). On PG 9-11, selects ''::text constant to avoid parse error. - Add SupportsGeneratedColumns to both describer and connector Circumstances, set when version_num >= 120000. - Improve diff comment explaining why Some↔Some expression comparison is skipped (PG normalizes expressions, making text comparison unreliable). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Exclude generated columns from unchecked create/update inputs - Propagate generation_expression for Unsupported type fields - Alphabetize generated test modules in mod.rs - Deduplicate attgenerated comment in postgres.rs - Add more specific assertions in negative tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 35 out of 35 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
schema-engine/connectors/sql-schema-connector/src/sql_schema_differ.rs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@schema-engine/sql-schema-describer/src/postgres.rs`:
- Around line 895-903: The code currently skips adding entries to
table_defaults/view_defaults when a column is a generated stored column, which
misaligns later defaults because TableColumnId(i)/ViewColumnId(i) are built by
enumeration; instead, when encountering a generated column in the
is_generated_stored branch you must still append a placeholder (e.g., an entry
representing None/no default) to the same vector so indices remain aligned with
column positions. Update the logic around is_generated_stored and container_id
to push a None/placeholder entry for the appropriate container (table_defaults
or view_defaults) rather than omitting the entry, keeping non-generated cases
pushing the actual default.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 06bbdad2-90e0-4722-9a25-2c2b2c6e9ca6
📒 Files selected for processing (8)
psl/psl/tests/attributes/generated_negative.rspsl/psl/tests/attributes/mod.rsquery-compiler/schema/src/build/input_types/objects/update_one_objects.rsquery-compiler/schema/src/build/mutations/create_one.rsschema-engine/connectors/sql-schema-connector/src/flavour/postgres.rsschema-engine/connectors/sql-schema-connector/src/sql_schema_calculator.rsschema-engine/connectors/sql-schema-connector/src/sql_schema_differ/column.rsschema-engine/sql-schema-describer/src/postgres.rs
- Fix column ID alignment: push None placeholder for generated columns in table_defaults/view_defaults instead of skipping, to keep positional indexing correct for subsequent columns. - Reword differ comment to accurately reflect that only Some↔None transitions are detected, not expression text changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reject @generated on non-PostgreSQL connectors with a clear error message. Uses Flavour::Postgres check since ConnectorCapability bitflags are at the u64 limit. Add negative test for MySQL. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
schema-engine/sql-schema-describer/src/postgres.rs (1)
874-897:⚠️ Potential issue | 🟠 MajorHandle PostgreSQL 18 virtual generated columns explicitly.
Line 876 only checks
attgenerated = 's'(stored generated columns). Virtual generated columns (attgenerated = 'v'), which are the default in PostgreSQL 18, are not recognized and will be misinterpreted as regular writable columns. Since theColumnstruct'sgeneration_expressionfield is currently documented to apply only to STORED columns and virtual columns cannot have ordinary defaults, virtual columns will fall through the normal default handling and be introspected incorrectly. Either explicitly rejectSome("v")or extend thegeneration_expressionfield to support both stored and virtual generated columns with a kind discriminant.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@schema-engine/sql-schema-describer/src/postgres.rs` around lines 874 - 897, The code only treats attgenerated == 's' (stored) as generated via the is_generated_stored check, so PostgreSQL 18 virtual generated columns ('v') are misclassified; update the logic around is_generated_stored / generation_expression / default to explicitly handle attgenerated == 'v' as a generated column (either by rejecting Some("v") with a clear error or by expanding the Column.generation_expression representation to include a kind/discriminant for Stored vs Virtual), ensure generation_expression is populated for virtual columns similarly to stored when appropriate, and ensure default is set to None for both stored and virtual generated columns so they are not treated as writable; refer to the is_generated_stored variable, generation_expression binding, and the default override when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@schema-engine/sql-schema-describer/src/postgres.rs`:
- Around line 874-897: The code only treats attgenerated == 's' (stored) as
generated via the is_generated_stored check, so PostgreSQL 18 virtual generated
columns ('v') are misclassified; update the logic around is_generated_stored /
generation_expression / default to explicitly handle attgenerated == 'v' as a
generated column (either by rejecting Some("v") with a clear error or by
expanding the Column.generation_expression representation to include a
kind/discriminant for Stored vs Virtual), ensure generation_expression is
populated for virtual columns similarly to stored when appropriate, and ensure
default is set to None for both stored and virtual generated columns so they are
not treated as writable; refer to the is_generated_stored variable,
generation_expression binding, and the default override when making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: ae9560ed-05ff-4c2e-b1ba-4aa8b1d6234d
📒 Files selected for processing (2)
schema-engine/connectors/sql-schema-connector/src/sql_schema_differ.rsschema-engine/sql-schema-describer/src/postgres.rs
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 35 out of 35 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
psl/psl-core/src/validate/validation_pipeline/validations/fields.rs
Outdated
Show resolved
Hide resolved
Use @generated (with @ prefix) and span_for_attribute("generated") for validation errors, matching Prisma's convention for error highlighting. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 35 out of 35 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 35 out of 35 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 35 out of 35 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add is_generated_column() check to filter_create_many_fields(), completing coverage across all mutation input types: - createOne (checked + unchecked) - createMany - updateOne (checked + unchecked) - updateMany (reuses updateOne filters) - upsert (reuses create/update inputs) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Expand DMMF test to verify statusPriority is excluded from all 6 writable input types (CreateInput, UncheckedCreateInput, CreateManyInput, UpdateInput, UncheckedUpdateInput, UpdateManyMutationInput) - Guard connector flavour check with datasource.is_some() to avoid panic on the empty connector (which has unreachable!() in flavour()) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 36 out of 36 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Implements support for PostgreSQL stored generated (computed) columns via a new
@generated("sql_expr")schema attribute, gated behind thegeneratedColumnspreview feature.Closes prisma/prisma#6336
Schema syntax
Generates:
Behavior
CreateInputandUpdateInput— Prisma Client never writes to themorderBy,where, etc.isGenerated: trueandisReadOnly: truedb pullround-trips correctly — introspectsattgeneratedfrompg_attributeand emits@generated("expr")@generatedon existing columns usesDROP COLUMN+ADD COLUMN(PostgreSQL doesn't supportALTER COLUMNfor generated columns until PG 17'sSET EXPRESSION)Validation
Rejects with clear error messages:
@generatedwithoutgeneratedColumnspreview feature@generatedcombined with@default@generatedcombined with@id@generatedcombined with@updatedAt@generatedon list fieldsChanges
GeneratedColumnsvariant, gated as active feature@generated("expr")attribute,is_generated_column+generation_expressiononScalarField@default,@id,@updatedAt, lists) + preview feature gateis_generated_column()method; excluded fromCreateInput/UpdateInputisGenerated: true,isReadOnly: trueGENERATED ALWAYS AS (expr) STOREDinsql-ddland postgres rendererGenerationExpressionchange variant; triggersDropAndRecreateColumnatt.attgenerated::textfrompg_attribute; skips default for generated cols@generated("expr")duringdb pullTests
19 tests, all passing:
Scope and known follow-up work
This PR is PostgreSQL-only. Known improvements for follow-up:
GENERATED ALWAYS AS ... STOREDsyntaxSET EXPRESSIONoptimization — PG 17+ supportsALTER COLUMN SET EXPRESSIONwhich avoidsDROP + ADDand preserves indexes; currently we use the PG 12-compatible pathPostgreSQL
GENERATED ALWAYS AS ... STOREDwas introduced in version 12 (Nov 2019). All Prisma-tested PG versions (12-16) support it.Summary by CodeRabbit
New Features
Validation
Migrations & Introspection
Tests