Moonshark/modules/sql/mysql.go

206 lines
5.0 KiB
Go

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{})
}