mysqlcommon

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 26, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package mysqlcommon holds the shared implementation between the MySQL and MariaDB drivers (forks with near-identical tooling). The underscore-prefixed directory keeps it out of "go build ./..." while remaining importable by the sibling driver packages.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BackupWith

func BackupWith(ctx context.Context, binary string, p driver.Profile, opt driver.BackupOpts, w io.Writer) error

BackupWith spawns the given dump binary (mysqldump or mariadb-dump) and streams its stdout to w. ctx cancellation propagates via exec.CommandContext.

func BuildDumpArgs

func BuildDumpArgs(p driver.Profile, opt driver.BackupOpts) []string

BuildDumpArgs assembles the mysqldump argument vector for a backup. The binary name itself is supplied by the caller (mysqldump vs mariadb-dump).

func BuildRestoreArgs

func BuildRestoreArgs(p driver.Profile, _ driver.RestoreOpts) []string

BuildRestoreArgs assembles the mysql client argument vector for a restore. The dump file is authoritative for shape; the restore client just pipes it in. Clean is a no-op here because mysqldump output already emits DROP TABLE IF EXISTS / CREATE TABLE, making the restore idempotent.

func DSN

func DSN(p driver.Profile) string

DSN builds a go-sql-driver/mysql connection string via mysql.Config.FormatDSN, the driver's own canonical builder, rather than hand-formatting. FormatDSN path-escapes the DBName and round-trips with the driver's ParseDSN, so we stay aligned with whatever the library considers valid. (Note: it does not percent-encode the user/password — those still rely on positional parsing — so a ':' in the username remains unsupported; MySQL usernames don't contain one in practice.)

func Open

func Open(p driver.Profile) (*sql.DB, error)

Open returns a database/sql handle for the profile. It does not probe the connection; callers ping as needed.

func RestoreWith

func RestoreWith(ctx context.Context, binary string, p driver.Profile, opt driver.RestoreOpts, r io.Reader) error

RestoreWith spawns the given client binary (mysql or mariadb) and pipes r into its stdin. ctx cancellation propagates via exec.CommandContext.

Types

type BinlogPosition

type BinlogPosition struct {
	File     string // e.g. "mysql-bin.000123"
	Position uint64
}

BinlogPosition identifies the binlog file + offset where incremental events begin. Captured at base-backup time and stored in the dump Envelope.

type Conn

type Conn struct {
	// contains filtered or unexported fields
}

Conn is the shared MySQL/MariaDB connection. The only per-fork difference is the dump/client binary names, injected at construction, so both drivers reuse this single implementation of the driver.Conn contract.

func NewConn

func NewConn(ctx context.Context, p driver.Profile, dumpBinary, clientBinary, binlogBinary, connOp, engine string) (*Conn, error)

NewConn opens + pings the database and returns a ready Conn. The ping is wrapped in a bounded retry (jobs.Retry, 3 attempts) — same policy as the Postgres driver (spec §4.3). connOp is the error-wrapping op label, e.g. "mysql.connect" / "mariadb.connect", so errors name the right driver. The three binary names (dump/client/binlog) are the only per-fork difference.

func (*Conn) ApplyChange

func (c *Conn) ApplyChange(ctx context.Context, ch canonical.CanonicalChange) error

ApplyChange applies one CanonicalChange to the database.

func (*Conn) Backup

func (c *Conn) Backup(ctx context.Context, opt driver.BackupOpts, w io.Writer) error

Backup streams a dump of the database to w via the fork's dump binary.

func (*Conn) BackupIncremental

func (c *Conn) BackupIncremental(ctx context.Context, since canonical.Position, w io.Writer) (canonical.Position, error)

BackupIncremental captures the BOUNDED change set from `since` to the current end-of-binlog, serializing each CanonicalChange to w as JSONL, and returns the end Position reached.

Bounding mechanism: the end binlog coordinates are captured up front via CaptureBinlogPosition and passed to the shared binlog decode loop as a stop target. Parsing returns cleanly at the first "# at" marker that reaches or passes the captured end offset in the end file, so every event up to it is emitted and none past it. This reuses StreamChanges' decode machinery so the incremental body is engine-neutral JSONL that the restore path replays via ApplyChange (rather than raw binlog bytes).

This path is exercised against a live log_bin=ON, binlog_format=ROW server only in CI; it is not validated locally (no MySQL/MariaDB here).

func (*Conn) CaptureBinlogPosition

func (c *Conn) CaptureBinlogPosition(ctx context.Context) (BinlogPosition, error)

CaptureBinlogPosition records the current binlog coordinates. Tries the MySQL 8.4+ statement first, then the pre-8.4 form, so it works across versions and both forks.

func (*Conn) Close

func (c *Conn) Close() error

Close releases the underlying connection pool.

func (*Conn) ConsumeCanonical

func (c *Conn) ConsumeCanonical(ctx context.Context, r io.Reader) error

ConsumeCanonical reads a stream produced by EmitCanonical and replays it into the database.

func (*Conn) CurrentPosition

func (c *Conn) CurrentPosition(ctx context.Context) (canonical.Position, error)

CurrentPosition returns the server's current binlog coordinates as a canonical Position. app.Backup calls this right after a full backup so the base dump's Envelope records where the first incremental should resume from.

func (*Conn) EmitCanonical

func (c *Conn) EmitCanonical(ctx context.Context, schema *canonical.CanonicalSchema, w io.Writer) error

EmitCanonical writes a table-by-table snapshot of schema as JSONL to w.

func (*Conn) Inspect

func (c *Conn) Inspect(ctx context.Context) (*driver.Schema, error)

func (*Conn) InspectSchema

func (c *Conn) InspectSchema(ctx context.Context) (*canonical.CanonicalSchema, error)

InspectSchema queries information_schema for tables and primary keys, returning a CanonicalSchema.

func (*Conn) Restore

func (c *Conn) Restore(ctx context.Context, opt driver.RestoreOpts, r io.Reader) error

Restore pipes r into the fork's client binary.

func (*Conn) StreamChanges

func (c *Conn) StreamChanges(ctx context.Context, from canonical.Position, emit func(canonical.CanonicalChange) error) (canonical.Position, error)

StreamChanges streams binlog ROW events from `from` as engine-neutral CanonicalChanges, decoding the fork's binlog tool's --verbose pseudo-SQL (### INSERT/UPDATE/DELETE … ### @N=…). Bounded callers cancel ctx at a target position; unbounded callers stream until ctx cancel. ctx cancellation is the normal stop signal and is NOT reported as an error.

Column positions (@1,@2,…) are mapped to names via information_schema (cached per table); the key is the table's primary-key columns. UPDATE events carry a WHERE (old image) block for the key and a SET (new image) block for Values.

NOTE: this parser is structurally complete but UNPROVEN locally (no MySQL here). The pseudo-SQL grammar is stable across MySQL/MariaDB --verbose output, but value typing (everything decodes as a string) and edge cases (multi-row events, NULL rendering, quoting) need validation against a live log_bin=ON, binlog_format=ROW server in CI.

func (*Conn) ValidateBinlogFormat

func (c *Conn) ValidateBinlogFormat(ctx context.Context) error

ValidateBinlogFormat returns a CodeUser error if binlog_format != ROW.

func (*Conn) Verify

func (c *Conn) Verify(_ context.Context, r io.Reader) (*driver.VerifyReport, error)

Verify performs a checksum-only check on the dump stream. Header-format checks land in Phase F when the siphon envelope exists.

type Fork

type Fork int

Fork identifies which MySQL-family engine a connection is talking to.

const (
	ForkUnknown Fork = iota
	ForkMySQL
	ForkMariaDB
)

func DetectFork

func DetectFork(ctx context.Context, db *sql.DB) (Fork, string, error)

DetectFork queries SELECT VERSION() and classifies the server as MySQL or MariaDB. MariaDB embeds "mariadb" in its version string; everything else that responds is treated as MySQL. Exported for cross-driver use even where callers don't yet branch on the result.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL