package database import ( "fmt" "strings" "git.secnex.io/secnex/taro-bot/config" "git.secnex.io/secnex/taro-bot/utils" "git.secnex.io/secnex/masterlog" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" ) type DatabaseConfiguration struct { Host string Port string User string Password string Database string } var DB *gorm.DB func NewDatabaseConfiguration(host, port, user, password, database string) *DatabaseConfiguration { return &DatabaseConfiguration{ Host: host, Port: port, User: user, Password: password, Database: database, } } func NewDatabaseConfigurationFromConfig(config *config.Config) *DatabaseConfiguration { return &DatabaseConfiguration{ Host: config.DatabaseHost, Port: config.DatabasePort, User: config.DatabaseUser, Password: config.DatabasePassword, Database: config.DatabaseName, } } func NewDatabaseConfigurationFromEnv() *DatabaseConfiguration { return &DatabaseConfiguration{ Host: utils.GetEnv("DB_HOST", "localhost"), Port: utils.GetEnv("DB_PORT", "5432"), User: utils.GetEnv("DB_USER", "postgres"), Password: utils.GetEnv("DB_PASSWORD", "postgres"), Database: utils.GetEnv("DB_DATABASE", "secnex"), } } func (c *DatabaseConfiguration) String() string { return fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable client_encoding=UTF8", c.Host, c.Port, c.User, c.Password, c.Database) } func (c *DatabaseConfiguration) Connect(config *config.Config, models ...interface{}) error { logLevel := logger.Silent if config.Debug { logLevel = logger.Info } db, err := gorm.Open(postgres.Open(c.String()), &gorm.Config{ Logger: logger.Default.LogMode(logLevel), }) if err != nil { return err } if err := AutoMigrate(db, models...); err != nil { return err } DB = db return nil } type SchemaProvider interface { Schema() string } func AutoMigrate(conn *gorm.DB, models ...interface{}) error { masterlog.Debug("Starting database auto-migration", map[string]interface{}{"model_count": len(models)}) err := conn.AutoMigrate(models...) if err != nil { // Check if error is about constraint that doesn't exist // This can happen when GORM tries to drop old constraints during migration errMsg := strings.ToLower(err.Error()) if strings.Contains(errMsg, "does not exist") && strings.Contains(errMsg, "constraint") { masterlog.Debug("Ignoring constraint drop error", map[string]interface{}{"error": err.Error()}) // Return nil to continue despite the constraint error return nil } masterlog.Debug("Auto-migration failed", map[string]interface{}{"error": err.Error()}) return err } masterlog.Debug("Database auto-migration completed successfully", map[string]interface{}{"model_count": len(models)}) return nil }