package sql import ( "context" "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) // MySQLDriver implements the Driver interface for MySQL type MySQLDriver struct{} func (d *MySQLDriver) Name() string { return "mysql" } func (d *MySQLDriver) Open(dsn string) (Connection, error) { db, err := sql.Open("mysql", dsn) if err != nil { return nil, fmt.Errorf("mysql: failed to open database: %w", err) } // Test the connection if err := db.Ping(); err != nil { db.Close() return nil, fmt.Errorf("mysql: failed to ping database: %w", err) } return &MySQLConnection{db: db}, nil } // MySQLConnection implements the Connection interface type MySQLConnection struct { db *sql.DB } func (c *MySQLConnection) Close() error { return c.db.Close() } func (c *MySQLConnection) Ping(ctx context.Context) error { return c.db.PingContext(ctx) } func (c *MySQLConnection) Begin(ctx context.Context) (Transaction, error) { tx, err := c.db.BeginTx(ctx, nil) if err != nil { return nil, fmt.Errorf("mysql: failed to begin transaction: %w", err) } return &MySQLTransaction{tx: tx}, nil } func (c *MySQLConnection) Query(ctx context.Context, query string, args ...any) (Rows, error) { rows, err := c.db.QueryContext(ctx, query, args...) if err != nil { return nil, fmt.Errorf("mysql: query failed: %w", err) } return &MySQLRows{rows: rows}, nil } func (c *MySQLConnection) QueryRow(ctx context.Context, query string, args ...any) Row { row := c.db.QueryRowContext(ctx, query, args...) return &MySQLRow{row: row} } func (c *MySQLConnection) Exec(ctx context.Context, query string, args ...any) (Result, error) { result, err := c.db.ExecContext(ctx, query, args...) if err != nil { return nil, fmt.Errorf("mysql: exec failed: %w", err) } return &MySQLResult{result: result}, nil } func (c *MySQLConnection) Prepare(ctx context.Context, query string) (Statement, error) { stmt, err := c.db.PrepareContext(ctx, query) if err != nil { return nil, fmt.Errorf("mysql: failed to prepare statement: %w", err) } return &MySQLStatement{stmt: stmt}, nil } // MySQLTransaction implements the Transaction interface type MySQLTransaction struct { tx *sql.Tx } func (t *MySQLTransaction) Commit() error { return t.tx.Commit() } func (t *MySQLTransaction) Rollback() error { return t.tx.Rollback() } func (t *MySQLTransaction) Query(ctx context.Context, query string, args ...any) (Rows, error) { rows, err := t.tx.QueryContext(ctx, query, args...) if err != nil { return nil, fmt.Errorf("mysql: transaction query failed: %w", err) } return &MySQLRows{rows: rows}, nil } func (t *MySQLTransaction) QueryRow(ctx context.Context, query string, args ...any) Row { row := t.tx.QueryRowContext(ctx, query, args...) return &MySQLRow{row: row} } func (t *MySQLTransaction) Exec(ctx context.Context, query string, args ...any) (Result, error) { result, err := t.tx.ExecContext(ctx, query, args...) if err != nil { return nil, fmt.Errorf("mysql: transaction exec failed: %w", err) } return &MySQLResult{result: result}, nil } func (t *MySQLTransaction) Prepare(ctx context.Context, query string) (Statement, error) { stmt, err := t.tx.PrepareContext(ctx, query) if err != nil { return nil, fmt.Errorf("mysql: failed to prepare transaction statement: %w", err) } return &MySQLStatement{stmt: stmt}, nil } // MySQLRows implements the Rows interface type MySQLRows struct { rows *sql.Rows } func (r *MySQLRows) Next() bool { return r.rows.Next() } func (r *MySQLRows) Scan(dest ...any) error { return r.rows.Scan(dest...) } func (r *MySQLRows) Columns() ([]string, error) { return r.rows.Columns() } func (r *MySQLRows) Close() error { return r.rows.Close() } func (r *MySQLRows) Err() error { return r.rows.Err() } // MySQLRow implements the Row interface type MySQLRow struct { row *sql.Row } func (r *MySQLRow) Scan(dest ...any) error { return r.row.Scan(dest...) } // MySQLResult implements the Result interface type MySQLResult struct { result sql.Result } func (r *MySQLResult) LastInsertId() (int64, error) { return r.result.LastInsertId() } func (r *MySQLResult) RowsAffected() (int64, error) { return r.result.RowsAffected() } // MySQLStatement implements the Statement interface type MySQLStatement struct { stmt *sql.Stmt } func (s *MySQLStatement) Close() error { return s.stmt.Close() } func (s *MySQLStatement) Query(ctx context.Context, args ...any) (Rows, error) { rows, err := s.stmt.QueryContext(ctx, args...) if err != nil { return nil, fmt.Errorf("mysql: statement query failed: %w", err) } return &MySQLRows{rows: rows}, nil } func (s *MySQLStatement) QueryRow(ctx context.Context, args ...any) Row { row := s.stmt.QueryRowContext(ctx, args...) return &MySQLRow{row: row} } func (s *MySQLStatement) Exec(ctx context.Context, args ...any) (Result, error) { result, err := s.stmt.ExecContext(ctx, args...) if err != nil { return nil, fmt.Errorf("mysql: statement exec failed: %w", err) } return &MySQLResult{result: result}, nil } func init() { // Register MySQL driver on import RegisterDriver("mysql", &MySQLDriver{}) }