db

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 29, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package db manages MySQL connections, statement execution and cancellation.

Index

Constants

View Source
const DialTimeout = 10 * time.Second

DialTimeout bounds how long a connection attempt waits before failing, so an unreachable host does not hang the UI.

View Source
const MaxQueryConns = 4

MaxQueryConns bounds the query pool. A handful is plenty: the user runs one statement at a time, and the spare slots exist so a stalled stream cannot starve the next one.

Variables

This section is empty.

Functions

func DSN

func DSN(ds *config.DataSource, password, addr string) string

DSN builds a driver connection string for ds.

addr overrides the host:port the driver dials, which is how an SSH tunnel is wired in: the datasource still describes the remote database while the driver connects to the local listener.

The DSN is assembled through mysql.Config rather than string concatenation so that passwords containing "@", "/" or ":" are escaped correctly.

func IsInterrupted

func IsInterrupted(err error) bool

IsInterrupted reports whether err is the server saying the statement was killed. Callers use it to present a cancellation as an outcome the user chose rather than as a failure.

func Probe

func Probe(ctx context.Context, ds *config.DataSource, password string) (string, error)

Probe opens a connection to ds and returns the server version.

sql.Open only validates the DSN, so it succeeds even against a host that is down. The version query is what actually proves reachability.

Types

type Conn

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

Conn is a live connection to one datasource.

It deliberately holds two separate connections to the same server:

  • pool serves the statements the user runs
  • control is reserved for KILL QUERY and catalog reads

MySQL will not accept another statement on a connection until the current result set has been read to the end, so without this split a long stream would block both cancellation and schema browsing — the two things most needed while a long stream is in flight.

func Open

func Open(ctx context.Context, ds *config.DataSource, password, addr string) (*Conn, error)

Open connects to ds. addr overrides the dialled address, which is how an SSH tunnel is wired in.

func (*Conn) Close

func (c *Conn) Close() error

Close releases both connections.

func (*Conn) DataSource

func (c *Conn) DataSource() *config.DataSource

DataSource returns the datasource this connection serves.

func (*Conn) Exec

func (c *Conn) Exec(ctx context.Context, sql string) (ExecResult, error)

Exec runs a statement that produces no result set.

func (*Conn) Query

func (c *Conn) Query(ctx context.Context, sql string, opt Options) *Stream

Query runs sql and streams the result.

It returns immediately; connecting, sending the statement and reading rows all happen in the background. Failures — including a syntax error — surface through Err once Events is closed.

func (*Conn) ServerVersion

func (c *Conn) ServerVersion() string

ServerVersion returns the version string reported at connection time.

func (*Conn) WithControl

func (c *Conn) WithControl(ctx context.Context, fn func(*sql.Conn) error) error

WithControl runs fn with exclusive use of the control connection.

This connection is reserved for cancellation and catalog reads, which is what keeps schema browsing responsive while the query pool streams a large result. Access goes through a callback rather than an accessor so that concurrent use — which would corrupt the protocol and kill the connection for good — cannot be expressed.

fn must not retain the connection beyond its return.

type Event

type Event struct {
	Kind EventKind

	// Columns and Types are set on EventColumns.
	Columns []string
	Types   []*sql.ColumnType

	// Rows is set on EventRows.
	Rows [][]any
}

Event is one update from a running statement.

There is deliberately no terminal event: the stream ends when Events is closed, and the reason is read from Err. A final event could be dropped when a cancelled stream closes, leaving the caller unable to tell a cancellation from a clean finish.

type EventKind

type EventKind int

EventKind identifies what a stream event carries.

const (
	// EventColumns arrives once, when the server returns the result header.
	EventColumns EventKind = iota
	// EventRows carries a batch of rows.
	EventRows
)

type ExecResult

type ExecResult struct {
	RowsAffected int64
	LastInsertID int64
}

ExecResult summarises a statement that returns no rows.

type Options

type Options struct {
	// ChunkSize is how many rows are gathered before a batch is published.
	ChunkSize int
	// MaxRows caps how many rows are read. Zero means no cap.
	MaxRows int
	// Schema is the one an unqualified name resolves against. Empty means the
	// schema the connection was opened with.
	Schema string
}

Options tunes how a result set is streamed.

type Stream

type Stream struct {
	// Events yields progress until it is closed.
	Events <-chan Event
	// contains filtered or unexported fields
}

Stream is a statement in flight.

Everything after Query returns is delivered on Events, which is closed when the statement ends for any reason. This shape exists because the driver's QueryContext blocks until the server produces a result header: a slow statement would otherwise freeze the caller — and in the TUI, the caller is the event loop that has to stay responsive enough to cancel it.

func (*Stream) Cancel

func (s *Stream) Cancel() error

Cancel stops the statement on the server.

Cancelling the context alone only detaches the client: the server keeps executing until it finishes. KILL QUERY, sent over the separate control connection, is what actually stops the work.

func (*Stream) Close

func (s *Stream) Close() error

Close releases the stream's resources. It is safe to call repeatedly.

func (*Stream) ConnectionID

func (s *Stream) ConnectionID() uint64

ConnectionID returns the server-side connection id, or zero if the statement has not reached the server yet.

func (*Stream) Err

func (s *Stream) Err() error

Err reports why the stream ended, once Events is closed. It is nil when the result set was read to the end.

This mirrors sql.Rows and bufio.Scanner: iterate until the source is exhausted, then ask why it stopped.

func (*Stream) Truncated

func (s *Stream) Truncated() bool

Truncated reports whether the stream stopped at Options.MaxRows rather than at the end of the result set.

func (*Stream) WaitConnectionID

func (s *Stream) WaitConnectionID(ctx context.Context) (uint64, error)

WaitConnectionID blocks until the server-side connection id is known.

Jump to

Keyboard shortcuts

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