Files
mysql/CHANGELOG.md
Rene Nochebuena f43fc8056c feat(mysql)!: promote to v1.0.0 — BeginTx with isolation levels, Stats, bump all deps to v1.0.0
Add BeginTx(ctx, *sql.TxOptions) to Client interface for explicit transaction isolation
level control; Begin refactored as a convenience wrapper calling BeginTx(ctx, nil).
Add Stats() sql.DBStats to Component interface for connection pool observability.
Bump all micro-lib dependencies (logz, health, launcher, xerrors) from v0.9.0 to v1.0.0.
API committed as stable.
2026-05-12 01:20:35 +00:00

5.6 KiB

Changelog

All notable changes to this module will be documented in this file.

The format is based on Keep a Changelog, and this module adheres to Semantic Versioning.

1.0.0 — 2026-05-12

Added

  • Client.BeginTx(ctx context.Context, opts *sql.TxOptions) (Tx, error) — starts a transaction with explicit isolation level and read-only options; accepts any *sql.TxOptions supported by database/sql.
  • Component.Stats() sql.DBStats — returns connection pool metrics (OpenConnections, WaitCount, WaitDuration, etc.) for observability and alerting; returns zero value when called before OnInit.

Changed

  • Client.Begin(ctx context.Context) (Tx, error) — refactored as a convenience wrapper calling BeginTx(ctx, nil); behavior is identical, no breaking change.
  • All micro-lib dependencies bumped from v0.9.1 to v1.0.0: logz, health, launcher, xerrors.

Unchanged

All other API (Executor, Tx, Client, Component, UnitOfWork, Config, New, NewUnitOfWork, HandleError) is API-compatible with v0.9.1.

0.9.1 - 2026-03-20

Added

  • Config.Charset string (MYSQL_CHARSET, default "utf8mb4"): connection character set, sent as SET NAMES <charset> during handshake. Previously hardcoded to utf8mb4.
  • Config.Loc string (MYSQL_LOC, default "UTC"): IANA timezone name used for time.TimeDATE/DATETIME conversion. Previously hardcoded to UTC.
  • Config.ParseTime string (MYSQL_PARSE_TIME, default "true"): controls driver-level DATE/DATETIMEtime.Time mapping. Valid values "true" / "false". Previously hardcoded to true.

Changed

  • Config.DSN(): now derives charset, loc, and parseTime from the new Config fields instead of hardcoded literals. Empty fields fall back to their respective defaults, preserving identical DSN output for callers that do not set the new fields.
  • Removed unused net/url.URL construction from DSN(); the method now builds params directly with url.Values.

Notes

  • Backward compatible. Existing Config literals that do not set Charset, Loc, or ParseTime produce the same DSN as v0.9.0 (charset=utf8mb4&loc=UTC&parseTime=true).
  • Collation via DSN is not supported. go-sql-driver v1.8.x negotiates the collation using a 1-byte handshake ID (max 255). MariaDB 11.4+ collations such as utf8mb4_uca1400_as_cs carry IDs > 255 and will cause a connection error if set in the DSN. Set the desired collation in schema migrations at the database/table level.

0.9.0 - 2026-03-18

Added

  • Executor interface: ExecContext, QueryContext, QueryRowContext using database/sql types (sql.Result, *sql.Rows, *sql.Row).
  • Tx interface: embeds Executor and adds Commit() error and Rollback() error (no context argument, matching database/sql semantics).
  • Client interface: GetExecutor(ctx context.Context) Executor, Begin(ctx context.Context) (Tx, error), Ping(ctx context.Context) error, HandleError(err error) error.
  • Component interface: composes launcher.Component, health.Checkable, and Client.
  • UnitOfWork interface: Do(ctx context.Context, fn func(ctx context.Context) error) error.
  • Config struct: fields Host, Port, User, Password, Name, MaxConns, MinConns, MaxConnLifetime, MaxConnIdleTime; settable via MYSQL_* environment variables with defaults (port 3306, max conns 5, idle conns 2, lifetime 1h, idle time 30m).
  • Config.DSN() string: constructs a go-sql-driver DSN in user:pass@tcp(host:port)/db?parseTime=true&loc=UTC format.
  • New(logger logz.Logger, cfg Config) Component: returns a *sql.DB-backed component; the connection is opened lazily in OnInit.
  • Lifecycle hooks: OnInit calls sql.Open, sets pool limits, and parses duration config fields; OnStart pings with a 5-second timeout; OnStop closes the *sql.DB.
  • health.Checkable implementation: HealthCheck delegates to Ping; Name() returns "mysql"; Priority() returns health.LevelCritical.
  • NewUnitOfWork(logger logz.Logger, client Client) UnitOfWork: wraps a Client to provide transactional Do semantics; rolls back and logs on error, commits on success.
  • HandleError(err error) error (package-level function): maps *mysqldrv.MySQLError error numbers to xerrors — 1062 (duplicate entry) → ErrAlreadyExists; 1216, 1217, 1451, 1452 (foreign key violations) → ErrInvalidInput; sql.ErrNoRowsErrNotFound; all other errors → ErrInternal.
  • Transaction context injection: the active *sql.Tx is stored under an unexported ctxTxKey{} context key; GetExecutor returns it when found, otherwise returns *sql.DB.
  • All *sql.DB reads guarded by sync.RWMutex for safe concurrent access.
  • go-sql-driver/mysql is imported with a blank identifier in mysql.go for driver side-effect registration, and as mysqldrv in errors.go to avoid the package name collision.

Design Notes

  • Tx.Commit() and Tx.Rollback() intentionally omit a context.Context argument, honestly reflecting the database/sql limitation rather than accepting and ignoring one.
  • The module is structurally parallel to postgres but uses database/sql types throughout; the two modules are intentionally type-incompatible.
  • MySQL error codes are matched by numeric constant via MySQLError.Number, not by string parsing, for stability across MySQL and MariaDB versions.