Escape reserved Dart keywords in SQL column names - #3838
Merged
simolus3 merged 1 commit intoJul 22, 2026
Merged
Conversation
Column names read from SQL were converted to Dart identifiers with `ReCase(name).camelCase` without checking for reserved keywords. A column named `class` (or any other reserved word) therefore produced invalid Dart such as `late final GeneratedColumn<int> class = ...`, which fails to parse. This surfaces via `make-migrations`: the generated schema snapshot embeds a `fixed_sql` block, and reading it back reconstructs tables directly from the `CREATE TABLE` statements, bypassing the serialized `getter_name` that the element-export path would otherwise use. `dartNameForSqlColumn` now appends a `$` to reserved words (e.g. `class` -> `class$`), and the drift table resolver routes column names through it instead of calling `ReCase` directly, so both `.drift` files and SQL-reconstructed schemas get valid identifiers.
mohanedy
force-pushed
the
fix/escape-dart-keyword-column-names
branch
from
July 21, 2026 13:18
8305941 to
d3dfa77
Compare
simolus3
approved these changes
Jul 21, 2026
simolus3
left a comment
Owner
There was a problem hiding this comment.
Thank you for your contribution! This looks good to me.
Contributor
Author
|
The |
|
I've been waiting for this fix. Great work! 🚀 |
Owner
|
I've fixed that warning, thanks for the ping! I'll release these changes later today. |
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.
Problem
A SQL column whose name is a reserved Dart keyword (e.g.
class) generates invalid Dart. The column name is turned into a Dart identifier viaReCase(name).camelCasewith no keyword check, so the generator emits code like:which fails to parse (
Can't have modifier 'late' here, etc.).This is most visible through
make-migrations. The serialized schema snapshot embeds afixed_sqlblock (the realCREATE TABLEstatements). When reading it back,SchemaReaderprefersfixed_sqland reconstructs tables directly from SQL (extractDriftElementsFromSql), which bypasses the serializedgetter_name. So even a table defined in Dart asIntColumn get productClass => integer().named('class')()— which normally generates fine — crashes when its schema snapshot is turned into a migration test database, because the reconstructed column falls back to the raw SQL nameclass.Stack (drift_dev 2.33.0, still present on
develop2.34.4):Fix
dartNameForSqlColumnnow appends$when the derived name is a reserved Dart keyword (class→class$), using the analyzer's authoritativeKeywordlist. Built-in identifiers (e.g.mixin) are valid identifiers and left untouched.table.dart) now routes column names throughdartNameForSqlColumninstead of callingReCase(...).camelCasedirectly, so both.driftfiles and SQL-reconstructed schemas produce valid identifiers. Views already used the shared helper.The SQL column name is unchanged — only the generated Dart getter/field/parameter identifier is escaped.
Tests
Added a resolver regression test (
test/analysis/resolver/drift/table_test.dart) covering aclasscolumn (escaped toclass$), a built-in identifier (mixin, unchanged), and a normal column. Fulltest/analysisandtest/writersuites pass locally (393 tests).Also verified end-to-end against a real project:
make-migrationspreviously crashed on aclasscolumn and now completes, and the generatedschema_vN.dartanalyzes clean.