feat: support generated (computed) columns via the generated tag - #230
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds SQLite support in the GORM SQLite dialector for STORED generated (computed) columns via a generated struct tag by appending the GENERATED ALWAYS AS (...) STORED clause to the column’s SQL type during migration.
Changes:
- Extend
Dialector.DataTypeOfto emit... GENERATED ALWAYS AS (<expr>) STOREDwhen aGENERATEDtag setting is present. - Add parsing helpers to treat
identity(optionally withalways/by default) as a reserved keyword (i.e., not a computed expression). - Add unit test coverage for the generated-column datatype rendering behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| sqlite.go | Adds generated-column handling in DataTypeOf and helpers to interpret the generated tag and reserve identity. |
| generated_test.go | Adds unit tests validating generated-column datatype rendering (including comma-containing expressions and reserved identity). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
h2zi
force-pushed
the
feat/generated-columns
branch
from
June 25, 2026 13:06
3a85a16 to
94d4368
Compare
Render SQLite STORED generated columns from a `generated` tag, keeping the generation expression separate from the column type: Total float64 `gorm:"->;generated:price * quantity"` // -> "total" real GENERATED ALWAYS AS (price * quantity) STORED The expression is taken verbatim, so commas inside it (e.g. coalesce(a, b)) are preserved; combine with the `->` read-only permission. The `identity` keyword is reserved for identity columns and is rendered through SQLite's native AUTOINCREMENT, so it is not treated as a computed-column expression. Relates to go-gorm/gorm#7191 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
h2zi
force-pushed
the
feat/generated-columns
branch
from
June 28, 2026 07:35
94d4368 to
13d7cf0
Compare
h2zi
added a commit
to libtnb/sqlite
that referenced
this pull request
Jul 31, 2026
Port of go-gorm/sqlite#230. DataTypeOf appends `GENERATED ALWAYS AS (expr) STORED` when a computed expression is present (SQLite 3.31+); the `identity` keyword stays reserved for the native AUTOINCREMENT handling, and a bare `generated` tag is ignored. The table-rebuild side was already in place here: getColumns() excludes generated columns from the INSERT INTO ... SELECT data copy, so AlterColumn/DropColumn on tables with computed columns work — covered by a dedicated regression test alongside the end-to-end and idempotency ones. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
davidpavlovschi
added a commit
to glebarez/sqlite
that referenced
this pull request
Aug 2, 2026
Ports every behaviour-changing upstream commit since 7544227, verified against the modernc backend: - 13be5e3 (go-gorm#236): preserve indexes, triggers, table options and views across table rebuilds - d450667 (go-gorm#235): HasColumn matches exactly via pragma_table_info - 69c4707 (go-gorm#230): generated (computed) columns via the generated tag - fc0cfd3 (go-gorm#207): parse CHECK/CONSTRAINT/FOREIGN KEY table-level lines - 5406e41 (go-gorm#198): case/whitespace-tolerant constraint matching - 02b8e06 (go-gorm#193): parseAllColumns state machine for composite keys - 7230345 (go-gorm#229): disable foreign keys during DropColumn - 6f07b51: don't overwrite caller-registered clause builders - 75dbf08 (go-gorm#222): accept tab between column name and type - bbca3b3 (go-gorm#185): exported Config and New(Config) constructor - 5df1f76 (go-gorm#219): remove stray Debug() from GetIndexes migrator.go, ddlmod.go and ddlmod_parse_all_columns.go are taken from upstream verbatim; sqlite.go is hand-merged to keep this fork's imports, DriverName, and its error-code-based Translate. Upstream's test files for these paths are ported unchanged. Refs #152
davidpavlovschi
added a commit
to glebarez/sqlite
that referenced
this pull request
Aug 2, 2026
…nslation (#155) * Port 11 behaviour fixes from go-gorm/sqlite (parity to upstream 525c431) Ports every behaviour-changing upstream commit since 7544227, verified against the modernc backend: - 13be5e3 (go-gorm#236): preserve indexes, triggers, table options and views across table rebuilds - d450667 (go-gorm#235): HasColumn matches exactly via pragma_table_info - 69c4707 (go-gorm#230): generated (computed) columns via the generated tag - fc0cfd3 (go-gorm#207): parse CHECK/CONSTRAINT/FOREIGN KEY table-level lines - 5406e41 (go-gorm#198): case/whitespace-tolerant constraint matching - 02b8e06 (go-gorm#193): parseAllColumns state machine for composite keys - 7230345 (go-gorm#229): disable foreign keys during DropColumn - 6f07b51: don't overwrite caller-registered clause builders - 75dbf08 (go-gorm#222): accept tab between column name and type - bbca3b3 (go-gorm#185): exported Config and New(Config) constructor - 5df1f76 (go-gorm#219): remove stray Debug() from GetIndexes migrator.go, ddlmod.go and ddlmod_parse_all_columns.go are taken from upstream verbatim; sqlite.go is hand-merged to keep this fork's imports, DriverName, and its error-code-based Translate. Upstream's test files for these paths are ported unchanged. Refs #152 * Bump gorm and the pure-Go sqlite backend gorm.io/gorm 1.25.7 to 1.31.2, github.com/glebarez/go-sqlite 1.21.2 to 1.22.0, which pulls modernc.org/sqlite 1.23.1 to 1.28.0. go mod tidy refreshes the indirect set. The go directive stays at 1.18: gorm 1.31.2 declares go 1.18 and go-sqlite 1.22.0 declares go 1.17, so nothing forces a raise. Test counts are unchanged, 15 top-level tests and 70 including subtests, all passing. Refs #152 * Document upstream parity in the README States the last upstream commit merged (525c431), the three divergences that are deliberate (pure-Go backend imports, DriverName "sqlite", error-code-based Translate), and the rule that backend-agnostic fixes go to go-gorm/sqlite first and come back as ports. Refs #152 * Translate CHECK constraint failures to gorm.ErrCheckConstraintViolated SQLITE_CONSTRAINT_CHECK (extended code 275) fell through Translate and reached the caller as a raw driver error, so TranslateError users had to string-match "CHECK constraint failed" to detect it. UNIQUE, PRIMARY KEY and FOREIGN KEY were already mapped. The test drives a real in-memory database: it migrates a model carrying a CHECK constraint, asserts the constraint is in the table DDL so a wrong failure cannot pass for the right one, then inserts a row that violates it. Without the mapping the test fails with the raw error, code 275. This mirrors the backport of the go-gorm#247 follow-up. Refs #152 * Fix unquoted constraints during table rebuilds
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
Support for SQLite STORED generated columns through the
generatedstruct tag, keeping the generation expression separate from the column type. Part of rounding out generated-column support across the GORM drivers (see go-gorm/postgres#345 for the PostgreSQL side, which also covers identity columns). Relates to go-gorm/gorm#7191.generatedvalue is taken verbatim as the expression of aSTOREDgenerated column (SQLite 3.31+). Commas inside the expression are preserved, sogenerated:coalesce(a, b)works.->so GORM treats the column as read-only (SQLite forbids writing generated columns).identitykeyword is reserved for identity columns; SQLite has no SQL-standard identity, sogenerated:identityis left to the existingAUTOINCREMENThandling rather than being mistaken for an expression.Implementation
DataTypeOfappends theGENERATED ALWAYS AS (...) STOREDclause when a computed expression is present; the base column type is computed exactly as before.Tests & verification
TestDataTypeOfGeneratedColumncovers the computed clause, comma-safe expressions, and the reservedidentitykeyword.CREATE TABLEemits"total" real GENERATED ALWAYS AS (price * quantity) STORED,INSERTomits the generated column, the read-back value is correct, and repeatedAutoMigrateruns are idempotent.🤖 Generated with Claude Code