Skip to content

feat: add @generated attribute for stored generated columns (PostgreSQL)#5800

Open
bilby91 wants to merge 11 commits intoprisma:mainfrom
crunchloop:feat/generated-columns
Open

feat: add @generated attribute for stored generated columns (PostgreSQL)#5800
bilby91 wants to merge 11 commits intoprisma:mainfrom
crunchloop:feat/generated-columns

Conversation

@bilby91
Copy link
Copy Markdown

@bilby91 bilby91 commented Mar 27, 2026

Summary

Implements support for PostgreSQL stored generated (computed) columns via a new @generated("sql_expr") schema attribute, gated behind the generatedColumns preview feature.

Closes prisma/prisma#6336

Schema syntax

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["generatedColumns"]
}

model Session {
  id             Int    @id @default(autoincrement())
  status         String
  statusPriority Int?   @generated("CASE status WHEN 'WAITING' THEN 1 WHEN 'FAILED' THEN 2 END")
}

Generates:

CREATE TABLE "Session" (
    "id" SERIAL NOT NULL,
    "status" TEXT NOT NULL,
    "statusPriority" INTEGER GENERATED ALWAYS AS (CASE status WHEN 'WAITING' THEN 1 WHEN 'FAILED' THEN 2 END) STORED,
    CONSTRAINT "Session_pkey" PRIMARY KEY ("id")
);

Behavior

  • Generated columns are excluded from CreateInput and UpdateInput — Prisma Client never writes to them
  • Generated columns are readable in queries and usable in orderBy, where, etc.
  • DMMF reports isGenerated: true and isReadOnly: true
  • Migrations are idempotent — no false drift on re-diff
  • db pull round-trips correctly — introspects attgenerated from pg_attribute and emits @generated("expr")
  • Adding/removing @generated on existing columns uses DROP COLUMN + ADD COLUMN (PostgreSQL doesn't support ALTER COLUMN for generated columns until PG 17's SET EXPRESSION)

Validation

Rejects with clear error messages:

  • @generated without generatedColumns preview feature
  • @generated combined with @default
  • @generated combined with @id
  • @generated combined with @updatedAt
  • @generated on list fields

Changes

Layer What
Preview feature GeneratedColumns variant, gated as active feature
PSL parser @generated("expr") attribute, is_generated_column + generation_expression on ScalarField
Validation Cross-attribute checks (@default, @id, @updatedAt, lists) + preview feature gate
Query compiler is_generated_column() method; excluded from CreateInput/UpdateInput
DMMF isGenerated: true, isReadOnly: true
DDL rendering GENERATED ALWAYS AS (expr) STORED in sql-ddl and postgres renderer
Schema diffing GenerationExpression change variant; triggers DropAndRecreateColumn
Introspection (read) att.attgenerated::text from pg_attribute; skips default for generated cols
Introspection (write) Renders @generated("expr") during db pull

Tests

19 tests, all passing:

Test Type Count
PSL positive (Int, String, optional) Unit 3
PSL negative (no feature, missing arg, non-string, +@default, +@id, +@updatedat, list) Unit 7
DDL rendering (expression, precedence, default fallback) Unit 3
DMMF (isReadOnly, isGenerated, excluded from inputs) Unit 1
Migration e2e (CREATE TABLE + idempotency) E2E, Postgres 1
Migration: add generated column to existing table E2E, Postgres 1
Migration: remove generated column E2E, Postgres 1
Migration: regular column → generated E2E, Postgres 1
Migration: generated column → regular E2E, Postgres 1

Scope and known follow-up work

This PR is PostgreSQL-only. Known improvements for follow-up:

  • MySQL/MariaDB — same GENERATED ALWAYS AS ... STORED syntax
  • CockroachDB — different computed column syntax
  • SET EXPRESSION optimization — PG 17+ supports ALTER COLUMN SET EXPRESSION which avoids DROP + ADD and preserves indexes; currently we use the PG 12-compatible path

PostgreSQL GENERATED ALWAYS AS ... STORED was introduced in version 12 (Nov 2019). All Prisma-tested PG versions (12-16) support it.

Summary by CodeRabbit

  • New Features

    • Support for SQL computed columns via @generated(...) and a generatedColumns preview feature.
  • Validation

    • Schema validation enforces preview gating and rejects invalid usages (with default/updatedAt/id, non-string args, list fields, or unsupported connectors).
  • Migrations & Introspection

    • Introspection, datamodel and migration generation recognize generated columns as read-only and render them as GENERATED ALWAYS AS (...) STORED.
  • Tests

    • Added comprehensive positive/negative parser, DMMF, migration and integration tests.

bilby91 and others added 2 commits March 27, 2026 18:08
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>
Copilot AI review requested due to automatic review settings March 27, 2026 21:27
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Mar 27, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 27, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds support for generated (computed) columns via a new @generated("expression") attribute: parsing, validation and preview-feature gating, schema introspection/describer updates, datamodel rendering, DMMF/query-compiler changes (read-only/excluded from inputs), migration/diff handling (drop-and-recreate), SQL rendering, and tests.

Changes

Cohort / File(s) Summary
PSL parsing & model
psl/parser-database/src/attributes.rs, psl/parser-database/src/types.rs, psl/parser-database/src/walkers/scalar_field.rs
Parse @generated("..."), validate argument shape, add is_generated_column and generation_expression to ScalarField, and expose is_generated_column() / generation_expression() on the scalar-field walker.
PSL validation & feature flag
psl/psl-core/src/common/preview_features.rs, psl/psl-core/src/validate/validation_pipeline/{validations.rs,validations/fields.rs}
Introduce GeneratedColumns preview feature and add per-field validation gating for @generated (feature + Postgres), plus cross-attribute forbids (@default, @updatedAt, @id, lists).
PSL tests & test helpers
psl/psl/tests/attributes/{generated_positive.rs,generated_negative.rs}, psl/psl/tests/attributes/mod.rs, psl/psl/tests/common/asserts.rs
Add positive and negative parser tests for @generated, register new test modules, and add assert_is_generated_column() test helper.
DMMF & query-compiler
query-compiler/dmmf/src/ast_builders/datamodel_ast_builder.rs, query-compiler/dmmf/src/tests/{test-schemas/postgres_generated_column.prisma,tests.rs}, query-compiler/query-structure/src/field/scalar.rs
Mark generated fields read-only in DMMF, set is_generated correctly, add ScalarField::is_generated_column() accessor, and add regression test + schema fixture.
Input type filtering
query-compiler/schema/src/build/mutations/{create_one.rs, input_types/objects/update_one_objects.rs}
Exclude generated columns from checked and unchecked create/update input construction so they do not appear in create/update inputs.
SQL DDL library & datamodel renderer
libs/sql-ddl/src/postgres.rs, schema-engine/datamodel-renderer/src/datamodel/field.rs
Add generation_expression to column/field types, render GENERATED ALWAYS AS (<expr>) STORED when present, and add Field::generated(...) to emit the attribute in datamodel output.
Schema describer & walkers
schema-engine/sql-schema-describer/src/{lib.rs,postgres.rs,mysql.rs,mssql.rs,sqlite.rs}, .../walkers/{column.rs,column/table_column.rs}
Add generation_expression to public Column, populate/default it in DB describers (Postgres reads attgenerated/expr and clears default for stored generated columns), add Circumstances::SupportsGeneratedColumns, and expose generation_expression() on walkers.
Connector flavour & introspection rendering
schema-engine/connectors/sql-schema-connector/src/flavour/postgres.rs, .../introspection/{introspection_pair/scalar_field.rs,rendering/scalar_field.rs}
Add connector capability for generated columns, enable describer capability when supported, add accessor to read generation expression from introspection pair and apply it during rendering.
Schema diff & migration
schema-engine/connectors/sql-schema-connector/src/{sql_schema_calculator.rs,sql_schema_differ.rs,sql_schema_differ/column.rs,sql_migration.rs}
Propagate generation_expression into sql::Column, add ColumnChange::GenerationExpression, detect generation-expression changes and treat them as drop-and-recreate, and render human-readable change text.
Migration tests & fixtures
schema-engine/sql-migration-tests/tests/{migrations/postgres.rs,single_migration_tests/postgres/generated_column.prisma}
Add Postgres migration tests and a Prisma fixture exercising @generated(...) (CASE expression) covering add/remove and toggle scenarios; tests gated by preview feature.
SQL schema connector renderer
schema-engine/connectors/sql-schema-connector/src/flavour/postgres/renderer.rs
Render generated/computed columns as GENERATED ALWAYS AS (<expr>) STORED and mark generation-expression changes to be handled via drop-and-recreate flow.
SQL describer consumers & small fixes
schema-engine/sql-schema-describer/src/{mysql.rs,mssql.rs,sqlite.rs}, schema-engine/sql-schema-describer/src/walkers/...
Explicitly set generation_expression: None where previously omitted and add walker accessors to surface generation expressions.
SQL DDL tests
libs/sql-ddl/src/postgres.rs
Add generation_expression to Column<'a>, update Display rendering to prefer generated expression over default, and add unit tests verifying rendering and precedence.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding support for @generated attribute on PostgreSQL stored generated columns.
Linked Issues check ✅ Passed The PR comprehensively addresses all primary coding objectives from issue #6336: @generated attribute support, exclusion from input types, introspection/round-trip support, migration handling, and validation with preview-feature gating.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing @generated support for PostgreSQL. Multi-dialect support is intentionally deferred as noted in the PR summary.
Docstring Coverage ✅ Passed Docstring coverage is 93.42% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 GenerationExpression change 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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🟠 Major

Unchecked create inputs should exclude generated columns.

The filter_unchecked_create_fields function does not exclude generated columns, which is inconsistent with filter_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

📥 Commits

Reviewing files that changed from the base of the PR and between 75cbdc1 and a3f9d1f.

📒 Files selected for processing (34)
  • libs/sql-ddl/src/postgres.rs
  • psl/parser-database/src/attributes.rs
  • psl/parser-database/src/types.rs
  • psl/parser-database/src/walkers/scalar_field.rs
  • psl/psl-core/src/common/preview_features.rs
  • psl/psl-core/src/validate/validation_pipeline/validations.rs
  • psl/psl-core/src/validate/validation_pipeline/validations/fields.rs
  • psl/psl/tests/attributes/generated_negative.rs
  • psl/psl/tests/attributes/generated_positive.rs
  • psl/psl/tests/attributes/mod.rs
  • psl/psl/tests/common/asserts.rs
  • query-compiler/dmmf/src/ast_builders/datamodel_ast_builder.rs
  • query-compiler/dmmf/src/tests/test-schemas/postgres_generated_column.prisma
  • query-compiler/dmmf/src/tests/tests.rs
  • query-compiler/query-structure/src/field/scalar.rs
  • query-compiler/schema/src/build/input_types/objects/update_one_objects.rs
  • query-compiler/schema/src/build/mutations/create_one.rs
  • schema-engine/connectors/sql-schema-connector/src/flavour/postgres/renderer.rs
  • schema-engine/connectors/sql-schema-connector/src/introspection/introspection_pair/scalar_field.rs
  • schema-engine/connectors/sql-schema-connector/src/introspection/rendering/scalar_field.rs
  • schema-engine/connectors/sql-schema-connector/src/sql_migration.rs
  • schema-engine/connectors/sql-schema-connector/src/sql_schema_calculator.rs
  • schema-engine/connectors/sql-schema-connector/src/sql_schema_differ.rs
  • schema-engine/connectors/sql-schema-connector/src/sql_schema_differ/column.rs
  • schema-engine/datamodel-renderer/src/datamodel/field.rs
  • schema-engine/sql-migration-tests/tests/migrations/postgres.rs
  • schema-engine/sql-migration-tests/tests/single_migration_tests/postgres/generated_column.prisma
  • schema-engine/sql-schema-describer/src/lib.rs
  • schema-engine/sql-schema-describer/src/mssql.rs
  • schema-engine/sql-schema-describer/src/mysql.rs
  • schema-engine/sql-schema-describer/src/postgres.rs
  • schema-engine/sql-schema-describer/src/sqlite.rs
  • schema-engine/sql-schema-describer/src/walkers/column.rs
  • schema-engine/sql-schema-describer/src/walkers/column/table_column.rs

bilby91 and others added 2 commits March 27, 2026 18:44
- 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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between a3f9d1f and 5d2a16d.

📒 Files selected for processing (8)
  • psl/psl/tests/attributes/generated_negative.rs
  • psl/psl/tests/attributes/mod.rs
  • query-compiler/schema/src/build/input_types/objects/update_one_objects.rs
  • query-compiler/schema/src/build/mutations/create_one.rs
  • schema-engine/connectors/sql-schema-connector/src/flavour/postgres.rs
  • schema-engine/connectors/sql-schema-connector/src/sql_schema_calculator.rs
  • schema-engine/connectors/sql-schema-connector/src/sql_schema_differ/column.rs
  • schema-engine/sql-schema-describer/src/postgres.rs

bilby91 and others added 2 commits March 27, 2026 19:09
- 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>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 | 🟠 Major

Handle 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 the Column struct's generation_expression field 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 reject Some("v") or extend the generation_expression field 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5d2a16d and c7dd947.

📒 Files selected for processing (2)
  • schema-engine/connectors/sql-schema-connector/src/sql_schema_differ.rs
  • schema-engine/sql-schema-describer/src/postgres.rs

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Move primary key validation for generated columns to model-level
(after @@id is processed) so it catches both single-field @id and
compound @@id. Add negative test for @@id([field]) case.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@bilby91 bilby91 requested a review from Copilot March 27, 2026 22:57
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

bilby91 and others added 2 commits March 27, 2026 22:05
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>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generated columns

3 participants