Generated columns
A generated column is computed by the database from an expression over other columns. It is
either STORED (written on each insert and update) or VIRTUAL (computed when read). Declare
it on the model and Besu writes it in CREATE TABLE, reads it back through introspection, and
never writes it.
The generated column is dropped from the insert struct and from set_model, so there is no
way to write to it by accident — the database would reject it.
Stored and virtual
STORED is the default. #[besu(generated = "..", stored = false)] asks for VIRTUAL, which
SQLite and MySQL support and PostgreSQL does not; on PostgreSQL the dialect maps it to stored,
because GENERATED ALWAYS AS ... VIRTUAL is not a thing there.
Reading one
A generated column is an ordinary column on the model, so a select returns it like any other.
It cannot be filtered on with an index unless you add one, and a virtual column cannot be
indexed in MySQL before 8.0.13.
Migrations
The differ compares the expression, folding ::type casts and identifier quoting, so
PostgreSQL's to_tsvector('english'::regconfig, bio) compares equal to
to_tsvector('english', bio).
- On PostgreSQL and MySQL, changing the expression is a drop and re-add of the column.
- On SQLite it is a table rebuild; the rebuild copies the base columns and lets the generated one recompute, rather than trying to insert into it.
What is checked
- The expression is opaque to the compiler: a typo is a database error at
push, not a compile error. - A field with
#[besu(generated = "..")]is excluded from the insert struct, so writing it is a compile error. - Introspection reads it back on all three dialects (
information_schemaon PostgreSQL and MySQL,PRAGMA table_xinfoon SQLite), sopull→pushconverges.
Gotchas
- A generated column still needs its Rust type to match what the expression produces, and the
compiler cannot check that. A
i32field over aTEXTexpression decodes as an error. - SQLite's
PRAGMA table_infohides generated columns; Besu usestable_xinfo. If you inspect the schema with another tool that usestable_info, the column will look missing. - A
VIRTUALcolumn cannot be added to a table that already hasSTOREDcolumns on older MySQL point releases; the server says so andpushreports it. - A hand-written
TableDefmust setauto_incrementalongsidegeneratedforset_modelto skip it. The derive does that for you.
