package database import ( "fmt" "os" "path/filepath" "sort" "strings" "github.com/jmoiron/sqlx" _ "github.com/lib/pq" ) // DB wraps the database connection type DB struct { *sqlx.DB } // Connect establishes a connection to the PostgreSQL database func Connect(databaseURL string) (*DB, error) { db, err := sqlx.Connect("postgres", databaseURL) if err != nil { return nil, fmt.Errorf("failed to connect to database: %w", err) } // Configure connection pool db.SetMaxOpenConns(25) db.SetMaxIdleConns(5) // Test the connection if err := db.Ping(); err != nil { return nil, fmt.Errorf("failed to ping database: %w", err) } return &DB{db}, nil } // Migrate runs database migrations func (db *DB) Migrate(migrationsPath string) error { // Read migration files files, err := os.ReadDir(migrationsPath) if err != nil { return fmt.Errorf("failed to read migrations directory: %w", err) } // Filter and sort .up.sql files var migrationFiles []string for _, file := range files { if strings.HasSuffix(file.Name(), ".up.sql") { migrationFiles = append(migrationFiles, file.Name()) } } sort.Strings(migrationFiles) // Execute migrations for _, filename := range migrationFiles { path := filepath.Join(migrationsPath, filename) content, err := os.ReadFile(path) if err != nil { return fmt.Errorf("failed to read migration %s: %w", filename, err) } if _, err := db.Exec(string(content)); err != nil { return fmt.Errorf("failed to execute migration %s: %w", filename, err) } fmt.Printf("✓ Executed migration: %s\n", filename) } return nil } // Close closes the database connection func (db *DB) Close() error { return db.DB.Close() }