package postgres import ( "database/sql" "fmt" "counter/internal/infrastructure/config" "counter/internal/infrastructure/logging" _ "github.com/lib/pq" ) // Connection manages the database connection type Connection struct { db *sql.DB } // NewConnection creates a new database connection func NewConnection(cfg *config.Config, logger logging.Logger) (*Connection, error) { db, err := sql.Open("postgres", cfg.DatabaseURL) if err != nil { return nil, fmt.Errorf("failed to open database: %w", err) } // Test the connection if err = db.Ping(); err != nil { return nil, fmt.Errorf("failed to ping database: %w", err) } logger.Info("✅ Database connection established successfully") conn := &Connection{db: db} // Create tables if err := conn.CreateTables(); err != nil { return nil, fmt.Errorf("failed to create tables: %w", err) } return conn, nil } // GetDB returns the database connection func (c *Connection) GetDB() *sql.DB { return c.db } // Close closes the database connection func (c *Connection) Close() error { return c.db.Close() } // CreateTables creates the necessary database tables func (c *Connection) CreateTables() error { queries := []string{ `CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, email VARCHAR(255) UNIQUE NOT NULL, password VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP )`, `CREATE TABLE IF NOT EXISTS counters ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, name VARCHAR(100) NOT NULL, description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP )`, `CREATE TABLE IF NOT EXISTS counter_entries ( id SERIAL PRIMARY KEY, counter_id INTEGER REFERENCES counters(id) ON DELETE CASCADE, value INTEGER NOT NULL, date DATE NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP )`, `CREATE INDEX IF NOT EXISTS idx_counters_user_id ON counters(user_id)`, `CREATE INDEX IF NOT EXISTS idx_counter_entries_counter_id ON counter_entries(counter_id)`, `CREATE INDEX IF NOT EXISTS idx_counter_entries_date ON counter_entries(date)`, } for _, query := range queries { if _, err := c.db.Exec(query); err != nil { return fmt.Errorf("failed to execute query: %w", err) } } return nil }