Skip to content

sea-orm-cli generate entity emits SQL generated columns (VIRTUAL/STORED) as writable fields #3094

Description

@JMLX42

Description

sea-orm-cli generate entity now emits SQL generated columns (GENERATED ALWAYS AS (...) VIRTUAL / STORED) as ordinary, writable entity fields. Earlier 2.0 release candidates omitted them entirely.

Because the emitted field carries no marker distinguishing it from a normal column, it becomes part of the derived ActiveModel. Any INSERT/UPDATE that sets the field — most commonly via model.into_active_model() (which sets every field) — sends the generated column to the database, and SQLite rejects it:

cannot INSERT into generated column "translation"
cannot UPDATE generated column "translation"

A generated column is read-only at the storage layer, so the generated entity should not expose it as a writable column. The previous behavior (skipping it) was correct for our usage.

Steps to Reproduce

  1. Create a SQLite database with a virtual generated column:

    CREATE TABLE node (
        id          INTEGER PRIMARY KEY,
        x           REAL,
        y           REAL,
        z           REAL,
        translation TEXT GENERATED ALWAYS AS (json_array(x, y, z)) VIRTUAL
    );
  2. Generate entities:

    sea-orm-cli generate entity -u 'sqlite://./test.sqlite' -o ./out
  3. Inspect out/node.rs.

Expected Behavior

The generated column should not be exposed as a writable column. Either omit it (as earlier RCs did), or generate it in a form that is excluded from INSERT/UPDATE — e.g. apply #[sea_orm(ignore)], which is the maintainer-recommended workaround for generated columns (discussion #2420). Ideally there would be a documented, supported way to keep such a column readable while never writing it.

Actual Behavior

translation is generated as a plain, writable column:

#[sea_orm(column_type = "Text", nullable)]
pub translation: Option<String>,

It is added to the Column enum and the derived ActiveModel, so writing the model fails at the database as shown above.

Reproduces How Often

Always, for any VIRTUAL/STORED generated column on SQLite.

Workarounds

  • Manually add #[sea_orm(ignore)] to each generated-column field after codegen (per discussion Possible to use generated columns with sea-orm? #2420). This stops the write, but the field is then excluded from SELECT as well (filled via Default), and the edit has to be re-applied on every regeneration since the CLI re-emits the plain column.
  • Pin sea-orm-cli to 2.0.0-rc.34, which did not emit these columns.

There is no column-level exclusion flag for generate entity (only --ignore-tables), so neither workaround can be expressed through the CLI.

Suggestion

It would help to either restore skipping of generated columns by default, or add a flag / emit #[sea_orm(ignore)] (or an equivalent read-only marker) automatically for columns reported as generated by the schema discovery (PRAGMA table_xinfo exposes the hidden = 2/3 flag for VIRTUAL/STORED on SQLite).

Versions

  • sea-orm / sea-orm-cli / sea-orm-migration: 2.0.0-rc.41 (regression vs 2.0.0-rc.34, which omitted these columns)
  • sea-schema: 0.18.0
  • sea-query: 1.0.1
  • Database: SQLite
  • OS: Linux

Filed by an AI agent (Claude Code, Anthropic) on behalf of, and reviewed by, a maintainer of a downstream project that hit this on a routine sea-orm-cli bump.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions