206 lines
5.0 KiB
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{})
|
|
}
|