fix(Migrator): make HasColumn match the exact column via pragma_table_info#235
fix(Migrator): make HasColumn match the exact column via pragma_table_info#235h2zi wants to merge 2 commits into
Conversation
…_info
HasColumn matched the column name as a LIKE substring against the table
DDL, so it reported columns as present when their name merely appeared
somewhere in the DDL text:
- an unquoted DDL with a first_name column makes HasColumn("name")
return true ("first_name text" contains "name ")
- a string default like DEFAULT 'name value' does the same
AutoMigrate then skips AddColumn for the missing column and later
queries fail with "no such column". Query pragma_table_info instead,
which returns the actual columns; COLLATE NOCASE keeps the comparison
case-insensitive like LIKE was. This matches how HasTable and
GetIndexes already query metadata instead of searching the SQL text.
There was a problem hiding this comment.
Pull request overview
This PR fixes false positives in the SQLite dialector’s Migrator.HasColumn by switching from substring matching against sqlite_master.sql to querying actual table metadata via pragma_table_info, preventing AutoMigrate from incorrectly skipping AddColumn when a column name only appears in DDL text (e.g., as part of another column name or a default string literal).
Changes:
- Replace
HasColumnimplementation to count exact column-name matches frompragma_table_info(?)usingCOLLATE NOCASE. - Add
TestHasColumnNoFalsePositiveto cover prior false-positive scenarios and confirm true positives.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| migrator.go | Updates HasColumn to check real column metadata via pragma_table_info instead of searching raw DDL text. |
| migrator_test.go | Adds a regression test ensuring HasColumn does not return true for substring/default-value matches. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| db, err := gorm.Open(Open("file:hascolumn_exact?mode=memory&cache=shared"), &gorm.Config{}) | ||
| if err != nil { | ||
| t.Fatalf("gorm.Open: %v", err) | ||
| } |
There was a problem hiding this comment.
Good catch — fixed in 225bd54: the pool is now closed via t.Cleanup, so the shared in-memory database is torn down between -count=N runs. Verified with go test -count=2 -run TestHasColumnNoFalsePositive.
Address review feedback: the named shared in-memory database lives as long as a connection remains open, leaking schema across repeated runs (go test -count=N).
What this PR does
HasColumnmatches the column name as a LIKE substring against the raw table DDL, which reports columns as present when their name merely appears somewhere in the DDL text:When this false positive hits during
AutoMigrate, the driver skipsAddColumnfor a genuinely missing column and later queries fail withno such column.The fix
Query
pragma_table_infoinstead, which returns the actual columns of the table:COLLATE NOCASEkeeps the comparison case-insensitive, as the LIKE patterns were. This matches howHasTableandGetIndexesalready query metadata instead of searching SQL text.Tests
TestHasColumnNoFalsePositivecovers both false-positive scenarios above plus the positive cases.🤖 Generated with Claude Code