diff --git a/internal/database/model/model.go b/internal/database/model/model.go index 17b68d5c4..a660b5f65 100644 --- a/internal/database/model/model.go +++ b/internal/database/model/model.go @@ -486,7 +486,7 @@ func HealMtprotoSecret(settings string) (string, bool) { // Setting stores key-value configuration settings for the 3x-ui panel. type Setting struct { Id int `json:"id" form:"id" gorm:"primaryKey;autoIncrement"` - Key string `json:"key" form:"key"` + Key string `json:"key" form:"key" gorm:"index:idx_settings_key"` Value string `json:"value" form:"value"` } diff --git a/internal/database/settings_index_test.go b/internal/database/settings_index_test.go new file mode 100644 index 000000000..abaffe584 --- /dev/null +++ b/internal/database/settings_index_test.go @@ -0,0 +1,30 @@ +package database + +import ( + "testing" + + "gorm.io/driver/sqlite" + "gorm.io/gorm" + "gorm.io/gorm/logger" + + "github.com/mhsanaei/3x-ui/v3/internal/database/model" +) + +// settings.key is read on nearly every request and job tick (getSetting +// WHERE key=?); AutoMigrate must create the index so those lookups don't +// full-scan the settings table past the large xrayTemplateConfig blob. gorm +// creates missing indexes on migrate, so this also covers existing DBs. +func TestAutoMigrateCreatesSettingsKeyIndex(t *testing.T) { + db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{ + Logger: logger.Default.LogMode(logger.Silent), + }) + if err != nil { + t.Fatalf("open sqlite: %v", err) + } + if err := db.AutoMigrate(&model.Setting{}); err != nil { + t.Fatalf("automigrate: %v", err) + } + if !db.Migrator().HasIndex(&model.Setting{}, "idx_settings_key") { + t.Errorf("expected idx_settings_key to exist after AutoMigrate") + } +}