/
iezhelev
/
cppsh_micro
Обзор
Документация
Войти
/
iezhelev
/
cppsh_micro
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
mayor-refactor
internal/database/init.go
169 строк
5 KB
iezhelev
major refactor
05 сен 2025, 16:59
05 сен 2025, 16:59
494658e
Код
Авторство
О чём код?
package database import ( "database/sql" "fmt" "log" "os" "github.com/golang-migrate/migrate/v4" "github.com/golang-migrate/migrate/v4/database/postgres" _ "github.com/golang-migrate/migrate/v4/source/file" // File-based migration source driver "github.com/jmoiron/sqlx" _ "github.com/lib/pq" ) // Init initializes the database and runs migrations. func Init() error { // Validate environment variables if err := validateConfig(); err != nil { return fmt.Errorf("invalid configuration: %w", err) } // Connect to the default database // defaultDB, err := connectToDefaultDB() // if err != nil { // return fmt.Errorf("failed to connect to default database: %w", err) // } // defer defaultDB.Close() // Check if the database exists dbName := os.Getenv("DB_NAME") // exists, err := databaseExists(defaultDB, dbName) // if err != nil { // return fmt.Errorf("failed to check if database exists: %w", err) // } // Create the database if it doesn't exist // if !exists { // log.Printf("Database %s does not exist. Creating...", dbName) // if err := createDatabase(defaultDB, dbName); err != nil { // return fmt.Errorf("failed to create database: %w", err) // } // log.Printf("Database %s created successfully.", dbName) // } // Connect to the target database targetDB, err := connectToTargetDB(dbName) if err != nil { return fmt.Errorf("failed to connect to target database: %w", err) } defer targetDB.Close() // Run migrations if err := runMigrations(targetDB); err != nil { return fmt.Errorf("failed to run migrations: %w", err) } log.Println("Database initialized successfully.") return nil } // validateConfig ensures all required environment variables are set. func validateConfig() error { requiredVars := []string{"DB_HOST", "DB_PORT", "DB_USER", "DB_PASSWORD", "DB_NAME"} for _, key := range requiredVars { if os.Getenv(key) == "" { return fmt.Errorf("missing required environment variable: %s", key) } } return nil } // connectToDefaultDB connects to the default PostgreSQL database. func connectToDefaultDB() (*sql.DB, error) { connStr := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=postgres sslmode=disable", os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD")) db, err := sql.Open("postgres", connStr) if err != nil { return nil, fmt.Errorf("failed to open database connection: %w", err) } if err := db.Ping(); err != nil { return nil, fmt.Errorf("failed to ping database: %w", err) } return db, nil } // databaseExists checks if the specified database exists. func databaseExists(db *sql.DB, dbName string) (bool, error) { query := `SELECT 1 FROM postgres WHERE datname = $1` var exists int err := db.QueryRow(query, dbName).Scan(&exists) if err != nil { if err == sql.ErrNoRows { return false, nil } return false, fmt.Errorf("failed to query database existence: %w", err) } return exists == 1, nil } // createDatabase creates the specified database. func createDatabase(db *sql.DB, dbName string) error { query := fmt.Sprintf("CREATE DATABASE %s", dbName) _, err := db.Exec(query) if err != nil { return fmt.Errorf("failed to execute CREATE DATABASE query: %w", err) } return nil } // connectToTargetDB connects to the target database. func connectToTargetDB(dbName string) (*sql.DB, error) { connStr := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), dbName) db, err := sql.Open("postgres", connStr) if err != nil { return nil, fmt.Errorf("failed to open database connection: %w", err) } if err := db.Ping(); err != nil { return nil, fmt.Errorf("failed to ping database: %w", err) } return db, nil } // runMigrations applies database migrations. func runMigrations(db *sql.DB) error { // Wrap the *sql.DB with sqlx dbx := sqlx.NewDb(db, "postgres") // Initialize the Postgres driver driver, err := postgres.WithInstance(dbx.DB, &postgres.Config{}) if err != nil { return fmt.Errorf("failed to initialize Postgres driver: %w", err) } // Initialize the file source fs, err := os.Open("migrations") if err != nil { return fmt.Errorf("failed to open migrations directory: %w", err) } defer fs.Close() /*source, err := file.WithInstance(fs) if err != nil { return fmt.Errorf("failed to initialize migration source: %w", err) }*/ // Initialize the migration instance /*m, err := migrate.NewWithInstance("file", source, "postgres", driver) if err != nil { return fmt.Errorf("failed to initialize migration instance: %w", err) } defer m.Close()*/ m, err := migrate.NewWithDatabaseInstance( "file://migrations", "postgres", driver) if err != nil { return fmt.Errorf("failed to apply migrations: %w", err) } defer m.Close() // Apply migrations if err := m.Up(); err != nil && err != migrate.ErrNoChange { return fmt.Errorf("failed to apply migrations: %w", err) } return nil }