Your Question
This is a bug, but I do not know how to write a test case for it. It is only observed through the logs. The use of the gorm:"default:null" tag is causing the AutoMigrate function to drop and recreate tables using that tag. Here is a minimal example:
package main
import (
"github.com/glebarez/sqlite"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)
type CreditCard struct {
gorm.Model
Number uint `gorm:"default:null"`
}
func main() {
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold
LogLevel: logger.Info, // Log level
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
Colorful: false, // Disable color
},
)
db, _ := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{Logger: newLogger})
db.AutoMigrate(&CreditCard{})
}
The document you expected this should be explained
When the gorm:"default:null" tag is present in the model, the table is created as expected the first time the application runs. The problem is observed in the logs the next time(s) the program runs. You can see that the table is dropped and the data is migrated to a new table:
[0.371ms] [rows:-] SELECT count(*) FROM sqlite_master WHERE type='table' AND name="credit_cards"
[0.105ms] [rows:2] SELECT sql FROM sqlite_master WHERE type IN ("table","index") AND tbl_name = "credit_cards" AND sql IS NOT NULL order by type = "table" desc
[0.043ms] [rows:-] SELECT * FROM `credit_cards` LIMIT 1
[0.023ms] [rows:1] PRAGMA foreign_keys
[0.021ms] [rows:-] SELECT sql FROM sqlite_master WHERE type = "table" AND tbl_name = "credit_cards" AND name = "credit_cards"
[0.472ms] [rows:0] CREATE TABLE `credit_cards__temp` (`id` integer,`created_at` datetime,`updated_at` datetime,`deleted_at` datetime,`number` integer DEFAULT null,PRIMARY KEY (`id`))
[0.045ms] [rows:0] INSERT INTO `credit_cards__temp`(`id`,`created_at`,`updated_at`,`deleted_at`,`number`) SELECT `id`,`created_at`,`updated_at`,`deleted_at`,`number` FROM `credit_cards`
[0.175ms] [rows:0] DROP TABLE `credit_cards`
[1.258ms] [rows:0] ALTER TABLE `credit_cards__temp` RENAME TO `credit_cards`
[0.033ms] [rows:-] SELECT count(*) FROM sqlite_master WHERE type = "index" AND tbl_name = "credit_cards" AND name = "idx_credit_cards_deleted_at"
[0.701ms] [rows:0] CREATE INDEX `idx_credit_cards_deleted_at` ON `credit_cards`(`deleted_at`)
I don't think this should be happening.
Expected answer
I expect the following behavior when the application is run the first time, as seen in the logs:
[0.343ms] [rows:-] SELECT count(*) FROM sqlite_master WHERE type='table' AND name="credit_cards"
[1.081ms] [rows:0] CREATE TABLE `credit_cards` (`id` integer,`created_at` datetime,`updated_at` datetime,`deleted_at` datetime,`number` integer DEFAULT null,PRIMARY KEY (`id`))
[0.695ms] [rows:0] CREATE INDEX `idx_credit_cards_deleted_at` ON `credit_cards`(`deleted_at`)
I expect the following behavior when the application is run the next time, as seen in the logs:
[0.386ms] [rows:-] SELECT count(*) FROM sqlite_master WHERE type='table' AND name="credit_cards"
[0.144ms] [rows:2] SELECT sql FROM sqlite_master WHERE type IN ("table","index") AND tbl_name = "credit_cards" AND sql IS NOT NULL order by type = "table" desc
[0.036ms] [rows:-] SELECT * FROM `credit_cards` LIMIT 1
[0.022ms] [rows:-] SELECT count(*) FROM sqlite_master WHERE type = "index" AND tbl_name = "credit_cards" AND name = "idx_credit_cards_deleted_at"
AutoMigrate detects the table exists.
Comment From: black-06
update gorm.io/driver/sqlite to v1.4.4
Comment From: dthomas-sensonix
@black-06 Thank you so much. Unfortunately I'm using https://github.com/glebarez/sqlite so I won't be able to pick up the fix immediately. Still, I'm glad you were able to find an issue and fix it.