mysql

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

README

mysql — MySQL statements and constructs

Everything MySQL in one import: the statements start here, mysql.Select, mysql.Insert, mysql.Update, mysql.Delete and the DDL constructors, and the constructs MySQL spells its own way are beside them: the upsert with its row alias, INSERT IGNORE, UPDATE and DELETE with LIMIT, locking reads, WITH ROLLUP, full-text MATCH, the JSON and text functions, and MySQL's keys, indexes, views and triggers.

Every construct is executed, not only rendered. contrib/driver-mysql runs each against a real MySQL 8.4, and the first runs found three that rendered cleanly and failed there.

The DDL detector in ddl_coverage_test.go classifies every statement the server's own HELP 'Data Definition' lists. Since 2026-09-24 it has no partial and no left-out entry: the table options, the remaining ALTER TABLE actions, the partition maintenance actions, the procedural trigger steps, ALTER VIEW, the EVENT and the stored routines all build, and what it still does not build is the seventeen statements it marks operator — server, storage and account administration, which a library's schema does not own.

Full documentation

The page for this package is docs/mysql/README.md, ending in a reference table generated from the source. The documentation index is ../docs/README.md.

Documentation

Overview

Package mysql holds what only MySQL has, and is where a MySQL statement starts.

It is the counterpart of pg and sqlite: the statements begin here, every MySQL construct is beside them, and contrib/driver-mysql executes what this package renders against a real MySQL 8.4, which is the only thing that turns a construct from asserted into proven.

Files: mysql.go (the guarded constructors), entry.go (the statements), write.go (upserts, INSERT IGNORE, UPDATE and DELETE with LIMIT), read.go (locking, WITH ROLLUP, functions), and the DDL in table.go and objects.go.

Index

Constants

View Source
const AllPartitions = kwAllPartitionsBare

AllPartitions names every partition of the table in a maintenance action, MySQL's ALL keyword. It is a partition name a table cannot have, because a bare ALL is a keyword in that position and an identifier there is quoted, so the two cannot be confused.

View Source
const UserSQLState = "45000"

UserSQLState is the SQLSTATE MySQL's own documentation uses for an application-raised error: class 45 is "unhandled user-defined exception" and is the one a trigger rejecting a row should raise, because every other class means something to the client driver.

Variables

View Source
var (
	// ErrPartitionKeyNotInKey is a primary or unique key that does not
	// include every partition column.
	ErrPartitionKeyNotInKey = errors.New("sqlb/mysql: every primary and unique key must include every partition column")
	// ErrPartitionForeignKey is a foreign key on a partitioned table, which
	// InnoDB does not support.
	ErrPartitionForeignKey = errors.New("sqlb/mysql: a partitioned table cannot have a foreign key")
	// ErrPartitionBounds is RANGE bounds that do not strictly increase, a
	// MAXVALUE that is not last, or a bound with the wrong number of values.
	ErrPartitionBounds = errors.New("sqlb/mysql: partition bounds are not strictly increasing, or MAXVALUE is not last")
	// ErrPartitionDefinition is a partition with no name, a name used twice,
	// a definition of the wrong kind for the partitioning, or none at all
	// where RANGE and LIST need at least one.
	ErrPartitionDefinition = errors.New("sqlb/mysql: a partition definition is missing, unnamed, duplicated or of the wrong kind")
)

The partitioning errors, each a table MySQL would refuse.

View Source
var ErrAutoIncrementZero = fmt.Errorf("%w: AUTO_INCREMENT must be at least 1", ErrUnknownKeyword)

ErrAutoIncrementZero is returned for an AUTO_INCREMENT of 0: MySQL reads it as "reset to the default", which is the opposite of what a caller asking for a specific next value means.

View Source
var ErrBadSQLState = errors.New("sqlb/mysql: a SIGNAL takes a five-character SQLSTATE outside class 00")

ErrBadSQLState is returned for a SIGNAL whose SQLSTATE is not five characters, or is class 00, which MySQL reads as success and refuses to signal.

View Source
var ErrBadSchedule = errors.New("sqlb/mysql: the event's schedule is incomplete or outside its named constants")

ErrBadSchedule is returned for a schedule outside what MySQL accepts: a zero Schedule, an interval unit outside the constants, or a quantity below one, which MySQL refuses with ER_EVENT_INTERVAL_NOT_POSITIVE.

View Source
var ErrCharacteristicNotAlterable = errors.New("sqlb/mysql: this routine characteristic cannot be altered")

ErrCharacteristicNotAlterable is returned for a characteristic in an ALTER that MySQL's ALTER FUNCTION and ALTER PROCEDURE do not take: determinism and the body are changed by dropping and recreating the routine.

View Source
var ErrConflictingCharacteristics = errors.New("sqlb/mysql: two routine characteristics of one kind")

ErrConflictingCharacteristics is returned for two characteristics of one category, NoSQL and ReadsSQLData say, which MySQL resolves by keeping the last rather than by failing.

View Source
var ErrEmptyBody = errors.New("sqlb/mysql: the routine has no body")

ErrEmptyBody is returned for a routine whose body is blank.

View Source
var ErrEmptyName = errors.New("sqlb/mysql: object has no name")

ErrEmptyName is returned for an object value with no name.

View Source
var ErrFunctionParamMode = errors.New("sqlb/mysql: a stored function's parameter takes no IN, OUT or INOUT")

ErrFunctionParamMode is returned for a stored function whose parameter carries IN, OUT or INOUT. MySQL's grammar gives a mode to a procedure's parameter only — a function's is always IN and the keyword is a parse error, measured on 8.4. A rendering test had asserted the IN form for a week before anything ran it.

View Source
var ErrMixedReferences = errors.New("sqlb/mysql: a foreign key references one table")

ErrMixedReferences is returned for a foreign key referencing two tables.

View Source
var ErrRenameAcrossTables = errors.New("sqlb/mysql: RenameKey names constraints of two tables")

ErrRenameAcrossTables is returned by RenameKey for two constraints of different tables: a key is renamed within its table.

View Source
var ErrUnknownKeyword = errors.New("sqlb/mysql: value outside its named constants")

ErrUnknownKeyword is returned for a value outside its named constants.

Functions

func AutoIncrement

func AutoIncrement[T integer](col sqlb.Expr[T]) ddl.ColumnClause[Dialect]

AutoIncrement makes col take the next value when an INSERT gives none. The column must be a key, usually the primary key, which MySQL checks.

func CharLength

func CharLength(e sqlb.Expr[string]) sqlb.Expr[int64]

CharLength renders char_length(e), the length in characters. MySQL's length() counts bytes, which is why a length check uses this.

func ClauseIn

func ClauseIn[K any](slot sqlb.Slot, construct string, render func(a *sqlb.Args) string) sqlb.Clause[Dialect, K]

ClauseIn makes a guarded clause for a statement slot, typed to MySQL and to the statement kind K.

func ColumnCollate

func ColumnCollate[T collatable](col sqlb.Expr[T], collation string) ddl.ColumnClause[Dialect]

ColumnCollate gives a text column a collation, utf8mb4_bin for a case-sensitive key, say; the default utf8mb4_0900_ai_ci is case- and accent-insensitive, so a UNIQUE on it refuses "Ada" beside "ada".

func ColumnComment

func ColumnComment[T any](col sqlb.Expr[T], text string) ddl.ColumnClause[Dialect]

ColumnComment attaches a comment to a column, where MySQL keeps it.

func ColumnInvisible

func ColumnInvisible[T any](col sqlb.Expr[T]) ddl.ColumnClause[Dialect]

ColumnInvisible hides a column from SELECT *, so it is returned only when named. It is how a column is added to a table an application selects with a star from, without that application seeing it before it is ready; a column's visibility is not a privilege and anyone naming it reads it.

func ColumnVisible

func ColumnVisible[T any](col sqlb.Expr[T]) ddl.ColumnClause[Dialect]

ColumnVisible returns a column to SELECT *, which is the default; it exists so a ModifyColumn that must keep the column visible can say so, since a property left out of a MySQL column redefinition is dropped.

func Expr

func Expr[T any](construct string, render func(a *sqlb.Args) string) sqlb.Expr[T]

Expr makes a guarded typed expression, for a helper this package lacks.

func Func

func Func[R any](construct, name string, args ...sqlb.SQLer) sqlb.Expr[R]

Func renders a guarded function call typed R.

func GeneratedStored

func GeneratedStored[T any](col, e sqlb.Expr[T]) ddl.ColumnClause[Dialect]

GeneratedStored makes col computed by e on write and stored.

func GeneratedVirtual

func GeneratedVirtual[T any](col, e sqlb.Expr[T]) ddl.ColumnClause[Dialect]

GeneratedVirtual makes col computed by e on read and stored nowhere.

func GroupConcat

func GroupConcat(e sqlb.Expr[string], sep string) sqlb.Expr[string]

GroupConcat renders group_concat(e SEPARATOR sep), the aggregate that joins a group's values into one string. The separator is written as a literal, because MySQL takes no parameter there, so it is an author's constant and a backslash in it is refused. The result is truncated silently at group_concat_max_len, 1024 bytes by default, which is the thing to know.

func Guard

func Guard(a *sqlb.Args, construct string) bool

Guard reports whether rendering may continue under the dialect in a, recording the construct as unsupported when it may not.

func IfNull

func IfNull[T any](e sqlb.Expr[*T], fallback sqlb.Expr[T]) sqlb.Expr[T]

IfNull renders ifnull(e, fallback).

func IntDiv

func IntDiv[T integerKind](l, r sqlb.Expr[T]) sqlb.Expr[T]

IntDiv renders l DIV r, integer division. MySQL's / always returns a decimal, so 7 / 2 is 3.5000 there, where Postgres and SQLite truncate an integer division; DIV is how MySQL says the other thing.

func Is

func Is(d sqlb.Dialect) bool

Is reports whether d is the MySQL dialect.

func JSONContains

func JSONContains(col sqlb.Expr[json.RawMessage], candidate json.RawMessage) sqlb.Predicate

JSONContains renders json_contains(col, candidate), whether the document contains the candidate, which must be valid JSON.

func JSONExtract

func JSONExtract(col sqlb.Expr[json.RawMessage], path string) sqlb.Expr[json.RawMessage]

JSONExtract renders json_extract(col, path), the JSON value at a path.

func JSONValue

func JSONValue(col sqlb.Expr[json.RawMessage], path string) sqlb.Expr[*string]

JSONValue renders json_unquote(json_extract(col, path)), the value at a path as text, NULL when the path is absent: the ->> operator, written as the functions it abbreviates so a bound path is allowed.

func Match

func Match(query string, mode MatchMode, first sqlb.Expr[string], more ...sqlb.Expr[string]) sqlb.Expr[float64]

Match renders MATCH(cols) AGAINST(query IN mode), a full-text search over columns with a FULLTEXT index, which the columns must be exactly. It is a relevance score, so it is both a filter and an ORDER BY term.

func New

func New[T any](col sqlb.Expr[T]) sqlb.Expr[T]

New is the value the INSERT tried to write to col, inside an OnDuplicateKeyUpdate: SET hits = hits + new.hits.

func NewRow

func NewRow[T any](col sqlb.Expr[T]) sqlb.Expr[T]

NewRow is a column's value after the change, in a trigger's body.

func NullSafeEq

func NullSafeEq[T any](l, r sqlb.Expr[T]) sqlb.Predicate

NullSafeEq renders l <=> r, MySQL's null-safe equality: true when both are NULL, where = would be NULL. It is the MySQL spelling of IS NOT DISTINCT FROM, which MySQL does not have.

func OldRow

func OldRow[T any](col sqlb.Expr[T]) sqlb.Expr[T]

OldRow is a column's value before the change, in a trigger's body. It is not New, which is the upsert's row alias; a trigger's NEW is a keyword.

func RegexpLike

func RegexpLike(e sqlb.Expr[string], pattern string) sqlb.Predicate

RegexpLike renders regexp_like(e, pattern), a regular-expression match.

func UTCNow

func UTCNow() sqlb.Expr[time.Time]

UTCNow renders utc_timestamp(6), the current instant in UTC to the microsecond, which is what a DATETIME(6) written and read in UTC wants; now() is in the session's time zone.

func UUID

func UUID() sqlb.Expr[string]

UUID renders uuid(), a version 1 UUID as text.

Types

type AlterAlgorithm

type AlterAlgorithm string

AlterAlgorithm is how MySQL performs an ALTER TABLE. It is the difference between a change that takes microseconds and one that copies every row, and naming it turns a wrong guess into an error instead of an outage: an ALTER asked for INSTANT that cannot be done instantly fails, where the default would quietly fall back to copying the table.

const (
	// AlgorithmInstant changes the table's metadata only. ADD COLUMN at the
	// end, RENAME COLUMN and a default change are instant on 8.0 or later.
	AlgorithmInstant AlterAlgorithm = "INSTANT"
	// AlgorithmInplace rebuilds the table in place without copying it to a
	// new file, and usually allows concurrent writes.
	AlgorithmInplace AlterAlgorithm = "INPLACE"
	// AlgorithmCopy copies every row into a new table, which is the slow path
	// and the one that blocks writes for the duration.
	AlgorithmCopy AlterAlgorithm = "COPY"
	// AlgorithmDefault lets MySQL pick the cheapest it can, which is what an
	// ALTER TABLE without the clause does.
	AlgorithmDefault AlterAlgorithm = "DEFAULT"
)

The algorithms, in increasing cost.

type AlterClause

type AlterClause = ddl.AlterClause[Dialect]

AlterClause is a MySQL ALTER TABLE action.

func AddConstraint

func AddConstraint(c Constraint) AlterClause

AddConstraint adds a unique key, a foreign key or a check.

func AddHashPartitions

func AddHashPartitions(n int) AlterClause

AddHashPartitions adds n partitions to a HASH or KEY partitioning.

func AddPartitions

func AddPartitions(first PartitionDef, more ...PartitionDef) AlterClause

AddPartitions adds RANGE or LIST partitions at the end. A new RANGE partition must lie above every existing one; the server checks that, since the existing bounds are not in the statement. A MAXVALUE partition is written for as many columns as the other partitions given bound; alone, it is written for one.

func Algorithm

func Algorithm(x AlterAlgorithm) AlterClause

Algorithm says how MySQL must perform the change, and fails the statement when it cannot be done that way. Write it last among the actions: MySQL's grammar puts it at the end of the list, and this module renders actions in the order given.

func AnalyzePartitions

func AnalyzePartitions(names ...string) AlterClause

AnalyzePartitions recomputes the key distribution of the named partitions, so the optimizer plans against current statistics after a bulk load. It returns a result set rather than failing; see the note above.

func CheckPartitions

func CheckPartitions(names ...string) AlterClause

CheckPartitions looks for corruption in the named partitions. It reports what it finds in a result set rather than failing, which is the whole reason a runner must query it; see the note above.

func CoalescePartitions

func CoalescePartitions(n int) AlterClause

CoalescePartitions removes n partitions from a HASH or KEY partitioning, redistributing their rows.

func ConvertToCharset

func ConvertToCharset(charset string) AlterClause

ConvertToCharset rewrites every text column of the table into charset, which is the one statement that fixes data already stored under another one. It rebuilds the table and it can fail on a key: converting to utf8mb4 makes a VARCHAR four bytes per character, so an index over a long one may no longer fit InnoDB's key limit.

func DisableKeys

func DisableKeys() AlterClause

DisableKeys stops MyISAM updating its non-unique indexes, so a bulk load writes rows once and the indexes are built in one pass by EnableKeys. InnoDB ignores it, with a warning, which is why it is documented as MyISAM only rather than as a general bulk-load trick.

func DiscardTablespace

func DiscardTablespace() AlterClause

DiscardTablespace detaches the table's data file, leaving the definition with no rows: the first half of moving a table between servers by copying its .ibd file. Every row is gone once it succeeds.

func DropCheck

func DropCheck(c TableConstraint) AlterClause

DropCheck drops a declared CHECK constraint.

func DropConstraint

func DropConstraint(c TableConstraint) AlterClause

DropConstraint drops a declared constraint whatever its kind, which is what a migration undoing an earlier one wants when the kind is not at hand; DropCheck, DropKey and DropForeignKey are the specific forms, and MySQL refuses each of those on a constraint of another kind.

func DropDefault

func DropDefault[T any](col sqlb.Expr[T]) AlterClause

DropDefault removes a column's default.

func DropForeignKey

func DropForeignKey(c TableConstraint) AlterClause

DropForeignKey drops a declared foreign key; its index stays.

func DropKey

func DropKey(c TableConstraint) AlterClause

DropKey drops a declared unique key.

func DropPartitions

func DropPartitions(names ...string) AlterClause

DropPartitions drops RANGE or LIST partitions and every row in them.

func DropPrimaryKey

func DropPrimaryKey() AlterClause

DropPrimaryKey drops the table's primary key. It is its own action because MySQL names every primary key PRIMARY and DropKey takes a declared TableConstraint, which a primary key never has.

func EnableKeys

func EnableKeys() AlterClause

EnableKeys rebuilds the indexes DisableKeys suspended.

func ForceRebuild

func ForceRebuild() AlterClause

ForceRebuild rebuilds the table with no other change, which is how InnoDB is made to rewrite it: with SetEngine it is the pair of statements that reclaim space after a large delete.

func ImportTablespace

func ImportTablespace() AlterClause

ImportTablespace attaches a data file copied from another server, the other half of the pair. The definition must match the file's exactly.

func Lock

func Lock(x AlterLock) AlterClause

Lock says how much concurrent access the change must allow, and fails when it cannot allow that much. Write it last, after Algorithm.

func ModifyColumn

func ModifyColumn(c ddl.ColumnSpec, with ...ddl.ColumnClause[Dialect]) AlterClause

ModifyColumn redefines a column in place, its type, nullability and default together: MySQL has no ALTER COLUMN ... TYPE, so a type change restates the whole definition, and a property left out is dropped. The column clauses must name it.

func OptimizePartitions

func OptimizePartitions(names ...string) AlterClause

OptimizePartitions rebuilds the named partitions and recomputes their statistics: REBUILD and ANALYZE in one pass. It returns a result set; see the note above.

func RawAlter

func RawAlter(sql string) AlterClause

RawAlter is an ALTER TABLE action written out, and it is this builder's one documented escape hatch.

It exists because the alternative is worse. MySQL's ALTER TABLE takes some forty table options — AVG_ROW_LENGTH, KEY_BLOCK_SIZE, COMPRESSION, ENCRYPTION, DATA DIRECTORY, STATS_PERSISTENT, TABLESPACE, UNION and the rest — which are an operator's storage tuning rather than a schema a library ships, and ORDER BY and the partition tablespace forms besides. Typing each would put a name in this package for a decision nobody here can make; leaving them unreachable would mean a caller who needs one abandons the builder for the whole statement and loses every check it performs. So this action is the seam: the typed actions keep their guarantees, and one option nobody typed does not cost them.

Nothing validates the string. It is written into the statement unchanged, so a value from outside the program must never reach it, and it names no column, so ALTER TABLE cannot check that it belongs to the table.

func RebuildPartitions

func RebuildPartitions(names ...string) AlterClause

RebuildPartitions rewrites the named partitions, which is how a partition left fragmented by a bulk delete is compacted without touching the rest of the table. Pass AllPartitions for every one.

func RemovePartitioning

func RemovePartitioning() AlterClause

RemovePartitioning makes the table unpartitioned, keeping every row.

func RenameIndex

func RenameIndex(from, to Index) AlterClause

RenameIndex renames a plain index of the table, the Index counterpart of RenameKey.

func RenameKey

func RenameKey(from, to TableConstraint) AlterClause

RenameKey renames a declared unique key within its table.

func RenameTo

func RenameTo(to sqlb.Table) AlterClause

RenameTo renames the table to to's name, as its own statement.

func ReorganizePartitions

func ReorganizePartitions(from []string, first PartitionDef, more ...PartitionDef) AlterClause

ReorganizePartitions replaces the named partitions with new definitions, moving their rows: the way to split MAXVALUE's partition when a new year arrives.

func RepairPartitions

func RepairPartitions(names ...string) AlterClause

RepairPartitions repairs corruption CheckPartitions found. It returns a result set; see the note above.

func SetAutoIncrement

func SetAutoIncrement(n uint64) AlterClause

SetAutoIncrement sets the value the next inserted row gets. MySQL will not lower it below the current maximum key: a smaller value is silently raised to that maximum plus one, so this reserves a range rather than rewinding one, which is why it is the statement run after importing rows with explicit ids.

func SetCheckEnforced

func SetCheckEnforced(c TableConstraint) AlterClause

SetCheckEnforced turns a declared CHECK constraint back on, and MySQL validates every existing row as it does so, so the statement fails when one violates it.

func SetCheckNotEnforced

func SetCheckNotEnforced(c TableConstraint) AlterClause

SetCheckNotEnforced turns a declared CHECK constraint off while keeping its definition, which is how a bulk load of rows that do not yet satisfy it is done without dropping and re-adding the constraint.

func SetColumnInvisible

func SetColumnInvisible[T any](col sqlb.Expr[T]) AlterClause

SetColumnInvisible hides a column from SELECT *; see ColumnInvisible.

func SetColumnVisible

func SetColumnVisible[T any](col sqlb.Expr[T]) AlterClause

SetColumnVisible and SetColumnInvisible change a column's visibility without restating its definition, which ModifyColumn would require.

func SetDefault

func SetDefault[T any](col sqlb.Expr[T], v T) AlterClause

SetDefault sets a column's default to a value of its type.

func SetDefaultCharset

func SetDefaultCharset(charset string) AlterClause

SetDefaultCharset changes the character set new columns of the table get. It leaves every existing column on its own character set, which is what makes it cheap and also what makes it the wrong statement for fixing a table already holding latin1 text: that is ConvertToCharset.

func SetEngine

func SetEngine(e Engine) AlterClause

SetEngine changes the table's storage engine, and is how a table is moved onto InnoDB. MySQL rebuilds the table to do it, copying every row, and running it with the table's current engine is the documented way to defragment it.

func SetIndexInvisible

func SetIndexInvisible(ix Index) AlterClause

SetIndexInvisible hides an index from the optimizer while keeping it maintained, which is how dropping one is tested: the queries plan as if it were gone, and SetIndexVisible undoes it instantly, where recreating a dropped index on a large table does not. The primary key cannot be hidden.

func SetIndexVisible

func SetIndexVisible(ix Index) AlterClause

SetIndexVisible makes an index available to the optimizer again.

func SetRowFormat

func SetRowFormat(f RowFormatKind) AlterClause

SetRowFormat changes how InnoDB stores a row, which rebuilds the table.

func SetTableCollate

func SetTableCollate(collation string) AlterClause

SetTableCollate changes the table's default collation, again for new columns only.

func SetTableComment

func SetTableComment(text string) AlterClause

SetTableComment replaces the table's comment. It touches the definition only, so it does not rebuild the table.

func TruncatePartitions

func TruncatePartitions(names ...string) AlterClause

TruncatePartitions deletes every row of the named partitions and keeps them.

func WithValidation

func WithValidation() AlterClause

WithValidation makes MySQL check every existing row against a change to a column an index covers, which is its default for a stored generated column.

func WithoutValidation

func WithoutValidation() AlterClause

WithoutValidation skips that check, which MySQL allows only for a change to a VIRTUAL generated column: the index is rebuilt from the new expression without verifying the old rows, so a change that alters the expression's result leaves index entries that no longer match the data.

type AlterEventQuery

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

AlterEventQuery is ALTER EVENT with no change yet, which has no Build: MySQL refuses an ALTER EVENT naming no part to change, so the statement is incomplete until one of the methods below has been called.

func AlterEvent

func AlterEvent(e Event) *AlterEventQuery

AlterEvent starts a change to an existing event. It is the statement that turns a job off (Status(EventDisable)) and back on without touching its definition, which is the reason it is worth having beside CreateEvent.

func (*AlterEventQuery) Comment

func (x *AlterEventQuery) Comment(text string) *AlterEventStatement

Comment replaces the event's comment.

func (*AlterEventQuery) Do

Do replaces the event's body.

func (*AlterEventQuery) On

On replaces the schedule.

func (*AlterEventQuery) OnCompletion

func (x *AlterEventQuery) OnCompletion(v Completion) *AlterEventStatement

OnCompletion replaces what happens once the event has no run left.

func (*AlterEventQuery) Rename

func (x *AlterEventQuery) Rename(to Event) *AlterEventStatement

Rename renames the event, which is also how it is moved to another schema.

func (*AlterEventQuery) Status

Status enables or disables the event.

type AlterEventStatement

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

AlterEventStatement is an ALTER EVENT with at least one change.

func (*AlterEventStatement) Build

func (x *AlterEventStatement) Build() (ddl.Script, error)

Build renders the statement.

func (*AlterEventStatement) Comment

Comment replaces the event's comment.

func (*AlterEventStatement) Do

Do replaces the event's body.

func (*AlterEventStatement) On

On replaces the schedule.

func (*AlterEventStatement) OnCompletion

OnCompletion replaces what happens once the event has no run left.

func (*AlterEventStatement) Rename

Rename renames the event.

func (*AlterEventStatement) Status

Status enables or disables the event.

type AlterLock

type AlterLock string

AlterLock is how much concurrent access the ALTER TABLE allows. Like AlterAlgorithm it fails rather than degrading: asking for NONE on a change that cannot allow writes is an error, which is what makes it safe to put in a migration that must not block.

const (
	// LockNone allows concurrent reads and writes.
	LockNone AlterLock = "NONE"
	// LockShared allows reads and blocks writes.
	LockShared AlterLock = "SHARED"
	// LockExclusive blocks both.
	LockExclusive AlterLock = "EXCLUSIVE"
	// LockDefault allows as much concurrency as the change permits, which is
	// what an ALTER TABLE without the clause does.
	LockDefault AlterLock = "DEFAULT"
)

The locking levels, in increasing strictness.

type AlterRoutineQuery

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

AlterRoutineQuery is an ALTER FUNCTION or ALTER PROCEDURE with no characteristic yet, which has no Build: MySQL refuses an ALTER naming nothing to change.

func AlterFunction

func AlterFunction(f Function) *AlterRoutineQuery

AlterFunction starts a change to a stored function's characteristics. Its body and its determinism are not among them; those are changed by dropping and recreating the function, and Characteristic refuses them with ErrCharacteristicNotAlterable rather than letting MySQL do it.

func AlterProcedure

func AlterProcedure(p Procedure) *AlterRoutineQuery

AlterProcedure starts a change to a stored procedure's characteristics.

func (*AlterRoutineQuery) Characteristic

Characteristic adds characteristics ALTER accepts, and so completes the statement.

func (*AlterRoutineQuery) Comment

Comment replaces the routine's comment, which MySQL's ALTER accepts.

type AlterRoutineStatement

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

AlterRoutineStatement is an ALTER FUNCTION or ALTER PROCEDURE with at least one characteristic.

func (*AlterRoutineStatement) Build

func (x *AlterRoutineStatement) Build() (ddl.Script, error)

Build renders the statement.

func (*AlterRoutineStatement) Characteristic

Characteristic adds further characteristics.

func (*AlterRoutineStatement) Comment

Comment replaces the routine's comment.

type AlterTableQuery

type AlterTableQuery = ddl.AlterTable[Dialect]

AlterTableQuery is an ALTER TABLE with no action yet, which has no Build.

func AlterTable

func AlterTable(t sqlb.Table) *AlterTableQuery

AlterTable starts an ALTER TABLE of t for MySQL.

type AlterTableReady

type AlterTableReady = ddl.AlterTableReady[Dialect]

AlterTableReady is an ALTER TABLE with at least one action.

type AlterViewQuery

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

AlterViewQuery is ALTER VIEW with no body yet, which has no Build: a view is altered by giving its new definition, so there is nothing to build until As has been called.

func AlterView

func AlterView(v View) *AlterViewQuery

AlterView starts a redefinition of an existing view. Unlike CreateView(v).OrReplace() it fails when the view does not exist.

func (*AlterViewQuery) Algorithm

Algorithm picks how MySQL processes the view.

func (*AlterViewQuery) As

As gives the view's new definition and completes the statement.

func (*AlterViewQuery) Columns

func (x *AlterViewQuery) Columns(first string, more ...string) *AlterViewQuery

Columns renames the query's columns.

func (*AlterViewQuery) Security

func (x *AlterViewQuery) Security(v ViewSecurity) *AlterViewQuery

Security picks whose privileges are checked when the view is read.

type AlterViewStatement

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

AlterViewStatement is a complete ALTER VIEW.

func (*AlterViewStatement) Build

func (x *AlterViewStatement) Build() (ddl.Script, error)

Build renders the statement.

func (*AlterViewStatement) WithCheckOption

func (x *AlterViewStatement) WithCheckOption(o CheckOption) *AlterViewStatement

WithCheckOption refuses a write through the view that it would not show, as on CREATE VIEW. A view's check option is part of its definition, so an ALTER that leaves this out removes one the view had.

type CheckClause

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

CheckClause is a named CHECK constraint, the same one ddl.Check writes, for ALTER TABLE ... ADD, which is MySQL's.

func Check

Check makes a named CHECK constraint. MySQL enforces them since 8.0.16; before that it parsed and ignored them, which is why the version matters.

func (CheckClause) ClauseTable

func (c CheckClause) ClauseTable() sqlb.Table

ClauseTable is the constraint's declared table.

func (CheckClause) NotEnforced

func (c CheckClause) NotEnforced() CheckClause

NotEnforced adds the CHECK turned off, which is how a constraint is declared over a table whose existing rows do not satisfy it yet; without it the ADD validates every row and fails. SetCheckEnforced turns it on once the rows are fixed.

func (CheckClause) Position

func (CheckClause) Position() ddl.Position

Position places the constraint among the table's elements.

func (CheckClause) TableClauseOf

func (CheckClause) TableClauseOf(Dialect)

TableClauseOf marks the clause as MySQL's.

func (CheckClause) WriteSQL

func (c CheckClause) WriteSQL(b *strings.Builder, a *sqlb.Args)

WriteSQL renders the constraint.

type CheckOption

type CheckOption int

CheckOption is what WITH CHECK OPTION checks.

const (
	Local CheckOption = iota + 1
	Cascaded
)

The check options.

type ColumnAction

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

ColumnAction is an ALTER TABLE action that defines a column and can say where it goes: ADD COLUMN, MODIFY COLUMN and CHANGE COLUMN.

func AddColumn

func AddColumn(c ddl.ColumnSpec, with ...ddl.ColumnClause[Dialect]) ColumnAction

AddColumn adds a column, with the MySQL placement the universal ddl.AddColumn cannot express. Use ddl.AddColumn where the position does not matter; this is the same action with FIRST or AFTER available.

func ChangeColumn

func ChangeColumn[T any](from sqlb.Expr[T], c ddl.ColumnSpec, with ...ddl.ColumnClause[Dialect]) ColumnAction

ChangeColumn renames a column and restates its definition in one action, which is the only way MySQL does both at once. MODIFY cannot rename and RENAME COLUMN cannot redefine, so a rename that also widens a type is this or it is two statements and two rebuilds.

func ModifyColumnAt

func ModifyColumnAt(c ddl.ColumnSpec, p Placement, with ...ddl.ColumnClause[Dialect]) ColumnAction

ModifyColumnAt is ModifyColumn with a placement, which also moves the column: MySQL rebuilds the table to do it.

func (ColumnAction) AlterClauseOf

func (ColumnAction) AlterClauseOf(Dialect)

AlterClauseOf marks the action as MySQL's.

func (ColumnAction) At

At places the column.

func (ColumnAction) ClauseTable

func (ColumnAction) ClauseTable() sqlb.Table

ClauseTable is none: the action's column carries the table.

func (ColumnAction) NamedColumns

func (x ColumnAction) NamedColumns() []ddl.ColumnRef

NamedColumns is the column the action defines, and the one it renames from, so ALTER TABLE checks both belong to the table.

func (ColumnAction) Standalone

func (ColumnAction) Standalone() bool

Standalone is false: MySQL combines a column action with others.

func (ColumnAction) WriteSQL

func (x ColumnAction) WriteSQL(b *strings.Builder, a *sqlb.Args)

WriteSQL renders the action.

type ColumnPair

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

ColumnPair is one column of a foreign key and the column it references.

func RefPair

func RefPair[T any](local, ref sqlb.Expr[T]) ColumnPair

RefPair pairs a column with the one it references, of one Go type.

type Completion

type Completion int

Completion is what MySQL does with an event that has no run left: a one-shot event that has fired, or a repeating one past its ENDS.

const (
	// Preserve keeps the event in the schema, disabled. It is what a
	// migration that declares an event wants, because a dropped event is one
	// the next Install would create again.
	Preserve Completion = iota + 1
	// NotPreserve drops the event, which is MySQL's default.
	NotPreserve
)

The completion behaviours.

type Constraint

type Constraint interface {
	TableClause
	// contains filtered or unexported methods
}

Constraint is a MySQL table constraint ALTER TABLE can add: a unique key, a foreign key or a check. The set is closed.

type CreateEventQuery

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

CreateEventQuery is CREATE EVENT with no schedule yet, which has no Build: ON SCHEDULE is not optional in MySQL's grammar, so the statement is incomplete until On has been called.

func CreateEvent

func CreateEvent(e Event) *CreateEventQuery

CreateEvent starts an event.

func (*CreateEventQuery) IfNotExists

func (x *CreateEventQuery) IfNotExists() *CreateEventQuery

IfNotExists makes creating an existing event a no-op.

func (*CreateEventQuery) On

On gives the schedule, which MySQL requires.

type CreateEventStatement

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

CreateEventStatement is a complete CREATE EVENT.

func (*CreateEventStatement) Build

func (x *CreateEventStatement) Build() (ddl.Script, error)

Build renders the statement.

type CreateIndexQuery

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

CreateIndexQuery is CREATE INDEX with no key yet, which has no Build.

func CreateIndex

func CreateIndex(ix Index, t sqlb.Table) *CreateIndexQuery

CreateIndex starts an index on t. MySQL has no IF NOT EXISTS for it, so a repeatable install checks information_schema.statistics first.

func (*CreateIndexQuery) Fulltext

func (x *CreateIndexQuery) Fulltext() *CreateIndexQuery

Fulltext makes a FULLTEXT index, which Match searches.

func (*CreateIndexQuery) On

On gives the key parts, at least one, and so completes the statement.

func (*CreateIndexQuery) Spatial

func (x *CreateIndexQuery) Spatial() *CreateIndexQuery

Spatial makes a SPATIAL index, which MySQL requires over a NOT NULL geometry column and which the geometry predicates use. It is the third kind beside Unique and Fulltext.

func (*CreateIndexQuery) Unique

func (x *CreateIndexQuery) Unique() *CreateIndexQuery

Unique makes the index refuse duplicate keys.

func (*CreateIndexQuery) Using

Using picks the index method.

type CreateIndexReady

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

CreateIndexReady is a CREATE INDEX with at least one key.

func (*CreateIndexReady) Algorithm

Algorithm says how MySQL must build the index and fails when it cannot be done that way; see the ALTER TABLE clause of the same name.

func (*CreateIndexReady) Build

func (x *CreateIndexReady) Build() (ddl.Script, error)

Build renders the statement.

func (*CreateIndexReady) IfNotExists

func (x *CreateIndexReady) IfNotExists() *CreateIndexReady

IfNotExists makes the index repeatable. MySQL has no IF NOT EXISTS for CREATE INDEX, so the statement carries a SkipIf query for the index in information_schema.statistics, which contrib/migrate's Execute runs first and a runner of your own must honour too; see ddl.Statement.SkipIf.

func (*CreateIndexReady) Lock

Lock says how much concurrent access building the index must allow.

func (*CreateIndexReady) With

func (x *CreateIndexReady) With(first IndexOption, more ...IndexOption) *CreateIndexReady

With adds index options.

type CreateRoutineQuery

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

CreateRoutineQuery is a CREATE FUNCTION or CREATE PROCEDURE with no body yet, which has no Build: a routine without one is not a statement.

func CreateFunction

func CreateFunction[T any](f Function, returns ddl.SQLType[T]) *CreateRoutineQuery

CreateFunction starts a stored function returning the Go type T, spelled by returns. It is a function rather than a method taking the type because a method cannot introduce a type parameter, and T has to enter somewhere for the return type to be checked at all.

func CreateProcedure

func CreateProcedure(p Procedure) *CreateRoutineQuery

CreateProcedure starts a stored procedure.

func (*CreateRoutineQuery) Body

Body gives the routine's body and completes the statement.

The body is written into the statement unchanged and nothing here parses or validates it, because it is not SQL: MySQL's stored-program language has its own declarations, handlers, cursors and control flow, and a builder for it would be a compiler for a language this module does not speak. Every other construct in this package renders text a dialect can check; a procedural block would look the same and check nothing, which is worse than an honest string. A value from outside the program must never reach it, for the same reason a raw SQL fragment must not.

A single-statement body is written out in full, RETURN x for a function or one statement for a procedure; a multi-statement one is the caller's own BEGIN ... END. No client DELIMITER is involved, because database/sql sends the statement whole.

func (*CreateRoutineQuery) Characteristic

Characteristic adds characteristics; at most one of each kind.

func (*CreateRoutineQuery) Comment

func (x *CreateRoutineQuery) Comment(text string) *CreateRoutineQuery

Comment attaches a comment to the routine, which information_schema reports. It is a characteristic in MySQL's grammar like the others, and it is a method rather than a RoutineCharacteristic because it carries a value and that set is a plain enumeration.

func (*CreateRoutineQuery) IfNotExists

func (x *CreateRoutineQuery) IfNotExists() *CreateRoutineQuery

IfNotExists makes creating an existing routine a no-op; MySQL 8.0.29 or later.

func (*CreateRoutineQuery) Param

func (x *CreateRoutineQuery) Param(first Param, more ...Param) *CreateRoutineQuery

Param adds parameters, in the order they are declared.

type CreateRoutineStatement

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

CreateRoutineStatement is a complete CREATE FUNCTION or CREATE PROCEDURE.

func (*CreateRoutineStatement) Build

func (x *CreateRoutineStatement) Build() (ddl.Script, error)

Build renders the statement.

type CreateTableAsStatement

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

CreateTableAsStatement is CREATE TABLE ... AS SELECT.

func CreateTableAs

func CreateTableAs(t sqlb.Table, body *SelectQuery) *CreateTableAsStatement

CreateTableAs creates t from the result of a query, deriving every column's name and type from the select list and filling the table in the same statement. It is how a backfill or a staging copy is made in one pass.

The derived types are MySQL's reading of the expressions, not this module's declarations, so a column built from an expression may come out wider or narrower than the one it was computed from; a table whose shape matters should be created by CreateTable or CreateTableLike and filled by an INSERT ... SELECT instead.

func (*CreateTableAsStatement) Build

func (x *CreateTableAsStatement) Build() (ddl.Script, error)

Build renders the statement.

func (*CreateTableAsStatement) IfNotExists

IfNotExists makes creating an existing table a no-op, and on this form that means the query does not run either: the table keeps the rows it had and nothing is appended. Measured on 8.4, because older MySQL did append here and the behaviour is the difference between a repeatable install and one that doubles its rows on the second run.

func (*CreateTableAsStatement) OnConflict

OnConflict says what to do with a row the new table's own unique key refuses.

func (*CreateTableAsStatement) Temporary

Temporary makes the new table a temporary one; see Temporary.

type CreateTableLikeStatement

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

CreateTableLikeStatement is CREATE TABLE ... LIKE.

func CreateTableLike

func CreateTableLike(t, src sqlb.Table) *CreateTableLikeStatement

CreateTableLike creates t with the structure of src: every column, every index and the table's attributes, and no rows. MySQL copies no foreign key and no table comment, which is the difference from a dump; it is how a staging table that must match a real one exactly is made without restating the definition and letting the two drift.

func (*CreateTableLikeStatement) Build

func (x *CreateTableLikeStatement) Build() (ddl.Script, error)

Build renders the statement.

func (*CreateTableLikeStatement) IfNotExists

IfNotExists makes creating an existing table a no-op.

func (*CreateTableLikeStatement) Temporary

Temporary makes the copy a temporary table; see Temporary.

type CreateTableQuery

type CreateTableQuery = ddl.CreateTable[Dialect]

CreateTableQuery is a CREATE TABLE with no column yet, which has no Build.

func CreateTable

func CreateTable(t sqlb.Table) *CreateTableQuery

CreateTable starts a CREATE TABLE of t for MySQL.

type CreateTableReady

type CreateTableReady = ddl.CreateTableReady[Dialect]

CreateTableReady is a CREATE TABLE with at least one column.

type CreateTriggerQuery

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

CreateTriggerQuery is CREATE TRIGGER with no timing yet.

func CreateTrigger

func CreateTrigger(tr Trigger) *CreateTriggerQuery

CreateTrigger starts a trigger.

func (*CreateTriggerQuery) After

After fires after the change on t.

func (*CreateTriggerQuery) Before

Before fires before the change on t, where the body may set NEW columns.

func (*CreateTriggerQuery) IfNotExists

func (x *CreateTriggerQuery) IfNotExists() *CreateTriggerQuery

IfNotExists makes creating an existing trigger a no-op; MySQL 8.0.29 or later.

type CreateTriggerStatement

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

CreateTriggerStatement is a complete CREATE TRIGGER.

func (*CreateTriggerStatement) Build

func (x *CreateTriggerStatement) Build() (ddl.Script, error)

Build renders the statement.

type CreateViewQuery

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

CreateViewQuery is CREATE VIEW with no body yet, which has no Build.

func CreateView

func CreateView(v View) *CreateViewQuery

CreateView starts a view.

func (*CreateViewQuery) Algorithm

Algorithm picks how MySQL processes the view.

func (*CreateViewQuery) As

As gives the body, a MySQL SELECT from the query builder.

func (*CreateViewQuery) Columns

func (x *CreateViewQuery) Columns(first string, more ...string) *CreateViewQuery

Columns renames the query's columns, which is how a view exposes a stable set of names over a query whose expressions change.

func (*CreateViewQuery) OrReplace

func (x *CreateViewQuery) OrReplace() *CreateViewQuery

OrReplace replaces an existing view, the idempotent form MySQL has.

func (*CreateViewQuery) Security

Security picks whose privileges are checked when the view is read.

type CreateViewStatement

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

CreateViewStatement is a complete CREATE VIEW.

func (*CreateViewStatement) Build

func (x *CreateViewStatement) Build() (ddl.Script, error)

Build renders the statement.

func (*CreateViewStatement) OrReplace

func (x *CreateViewStatement) OrReplace() *CreateViewStatement

OrReplace replaces an existing view.

func (*CreateViewStatement) WithCheckOption

func (x *CreateViewStatement) WithCheckOption(o CheckOption) *CreateViewStatement

WithCheckOption refuses a write through the view that it would not show.

type DeleteClause

type DeleteClause = sqlb.Clause[Dialect, sqlb.DeleteKind]

DeleteClause is a clause for a DELETE on MySQL.

func DeleteLimit

func DeleteLimit(n int64, order ...sqlb.OrderTerm) DeleteClause

DeleteLimit caps a DELETE at n rows, in the order given: the batched purge of an old-rows table. A single-table DELETE only.

type DeleteQuery

type DeleteQuery = sqlb.Delete[Dialect]

DeleteQuery is the statement Delete returns, with no Build until Where or All.

func Delete

func Delete(t sqlb.Table) *DeleteQuery

Delete starts a DELETE from t for MySQL.

type Dialect

type Dialect = mysql.Dialect

Dialect is the MySQL dialect, re-exported so a caller importing this package for its constructs needs no second import to name the engine.

type DropIndexStatement

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

DropIndexStatement is DROP INDEX ... ON.

func DropIndex

func DropIndex(ix Index, t sqlb.Table) *DropIndexStatement

DropIndex drops an index from its table. MySQL has no IF EXISTS for it.

func (*DropIndexStatement) Algorithm

Algorithm says how MySQL must drop the index. CREATE INDEX and DROP INDEX are both mapped to ALTER TABLE by the server, which is why both take it.

func (*DropIndexStatement) Build

func (x *DropIndexStatement) Build() (ddl.Script, error)

Build renders the statement.

func (*DropIndexStatement) IfExists

func (x *DropIndexStatement) IfExists() *DropIndexStatement

IfExists makes dropping a missing index a no-op, through a SkipIf query as CreateIndexReady.IfNotExists does, since MySQL has no DROP INDEX IF EXISTS.

func (*DropIndexStatement) Lock

Lock says how much concurrent access dropping the index must allow.

type DropStatement

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

DropStatement is DROP VIEW or DROP TRIGGER, with IF EXISTS.

func DropEvent

func DropEvent(e Event) *DropStatement

DropEvent drops an event.

func DropFunction

func DropFunction(f Function) *DropStatement

DropFunction drops a stored function.

func DropProcedure

func DropProcedure(p Procedure) *DropStatement

DropProcedure drops a stored procedure.

func DropTrigger

func DropTrigger(tr Trigger) *DropStatement

DropTrigger drops a trigger.

func DropView

func DropView(v View) *DropStatement

DropView drops a view.

func (*DropStatement) Build

func (x *DropStatement) Build() (ddl.Script, error)

Build renders the statement.

func (*DropStatement) IfExists

func (x *DropStatement) IfExists() *DropStatement

IfExists makes dropping a missing object a no-op.

type DropTableQuery

type DropTableQuery = ddl.DropTable[Dialect]

DropTableQuery is a DROP TABLE, complete from its constructor.

func DropTable

func DropTable(first sqlb.Table, more ...sqlb.Table) *DropTableQuery

DropTable drops one or more tables for MySQL, one statement per table.

type DropTemporaryTableStatement

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

DropTemporaryTableStatement is DROP TEMPORARY TABLE.

func DropTemporaryTable

func DropTemporaryTable(first sqlb.Table, more ...sqlb.Table) *DropTemporaryTableStatement

DropTemporaryTable drops temporary tables, one statement each.

The word is not decoration: DROP TABLE on a name that is both a temporary table and a permanent one drops the temporary, so the permanent table survives a drop that looked like it removed it, while DROP TEMPORARY TABLE refuses a permanent table outright. It is a statement of its own rather than a clause because ddl's DROP TABLE writes its clauses after the table name and MySQL's keyword goes before it.

func (*DropTemporaryTableStatement) Build

Build renders one statement per table.

func (*DropTemporaryTableStatement) IfExists

IfExists makes dropping a missing table a no-op.

type Engine

type Engine string

Engine is a MySQL storage engine. The set is closed to the three a library would ask for by name; anything else is an operator's choice made in the server's default, not in a schema a library ships.

const (
	// EngineInnoDB is the only one with transactions, foreign keys and row
	// locks, which is what a library's table needs. It is also the server
	// default, and writing it makes the table not depend on that default.
	EngineInnoDB Engine = "InnoDB"
	// EngineMemory holds the table in RAM and loses it on restart: a scratch
	// table, never one that owns data.
	EngineMemory Engine = "MEMORY"
	// EngineMyISAM has no transactions and locks the whole table; it is here
	// because a table inherited from an older schema may still be on it and
	// SetEngine(EngineInnoDB) is how it is moved off.
	EngineMyISAM Engine = "MyISAM"
)

The storage engines.

type Event

type Event struct{ Name string }

Event is a MySQL event, a statement the server runs on a schedule. Its name is unique per schema, and it is declared once so no statement types it twice.

type EventStatus

type EventStatus int

EventStatus is whether the scheduler runs the event.

const (
	// EventEnable runs the event on its schedule, which is the default.
	EventEnable EventStatus = iota + 1
	// EventDisable keeps the event and does not run it: the way a job is
	// turned off without losing its definition.
	EventDisable
	// EventDisableOnReplica runs the event on the source and not on a
	// replica, where the replicated rows arrive anyway; running it on both
	// would apply the work twice.
	EventDisableOnReplica
)

The statuses.

type ExchangePartitionClause

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

ExchangePartitionClause is EXCHANGE PARTITION ... WITH TABLE, which swaps a partition's rows with an unpartitioned table's in constant time, by exchanging the two tablespaces rather than moving rows.

It is the statement behind archiving: load a month into a plain table, then exchange it into the partitioned one. MySQL requires the two to have the identical structure, and it validates, row by row, that every row of the table belongs in the partition — which is linear in the rows and is what WithoutValidation turns off.

func ExchangePartition

func ExchangePartition(name string, with sqlb.Table) ExchangePartitionClause

ExchangePartition swaps the named partition with the unpartitioned table with, validating every row. The zero value of the clause has no partition name and fails Build with ErrEmptyName.

func (ExchangePartitionClause) AlterClauseOf

func (ExchangePartitionClause) AlterClauseOf(Dialect)

AlterClauseOf marks the action as MySQL's.

func (ExchangePartitionClause) NamedColumns

func (ExchangePartitionClause) NamedColumns() []ddl.ColumnRef

NamedColumns is none: the action names partitions and a table, not columns.

func (ExchangePartitionClause) Standalone

func (ExchangePartitionClause) Standalone() bool

Standalone is true: MySQL takes an EXCHANGE PARTITION as the only action of its ALTER TABLE.

func (ExchangePartitionClause) WithoutValidation

func (x ExchangePartitionClause) WithoutValidation() ExchangePartitionClause

WithoutValidation skips the per-row check that every row of the table belongs in the partition, which makes the exchange constant time on a large table. MySQL then stores rows that do not match the partition's bounds and no query will ever find them again, so this is for a table whose rows the caller has already constrained — the WHERE of the SELECT that built it.

func (ExchangePartitionClause) WriteSQL

func (x ExchangePartitionClause) WriteSQL(b *strings.Builder, a *sqlb.Args)

WriteSQL renders the action.

type FilteredDelete

type FilteredDelete = sqlb.FilteredDelete[Dialect]

FilteredDelete is a DELETE that has said which rows.

type FilteredUpdate

type FilteredUpdate = sqlb.FilteredUpdate[Dialect]

FilteredUpdate is an UPDATE that has said which rows.

type ForeignKeyClause

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

ForeignKeyClause is a FOREIGN KEY table constraint.

func ForeignKey

func ForeignKey(c TableConstraint, first ColumnPair, more ...ColumnPair) ForeignKeyClause

ForeignKey makes a named foreign key; InnoDB indexes its columns if no index does.

func References

func References[T any](local, ref sqlb.Expr[T]) ForeignKeyClause

References is the one-column foreign key.

func (ForeignKeyClause) ClauseTable

func (f ForeignKeyClause) ClauseTable() sqlb.Table

ClauseTable is the constraint's declared table, empty for References.

func (ForeignKeyClause) DescribeInto

func (f ForeignKeyClause) DescribeInto(t *schema.Table)

DescribeInto adds the foreign key.

func (ForeignKeyClause) NamedColumns

func (f ForeignKeyClause) NamedColumns() []ddl.ColumnRef

NamedColumns is the constraint's local columns.

func (ForeignKeyClause) OnDelete

OnDelete says what happens when the referenced row is deleted.

func (ForeignKeyClause) OnUpdate

OnUpdate says what happens when the referenced key changes.

func (ForeignKeyClause) Position

func (ForeignKeyClause) Position() ddl.Position

Position places the constraint among the table's elements.

func (ForeignKeyClause) TableClauseOf

func (ForeignKeyClause) TableClauseOf(Dialect)

TableClauseOf marks the clause as MySQL's.

func (ForeignKeyClause) WriteSQL

func (f ForeignKeyClause) WriteSQL(b *strings.Builder, a *sqlb.Args)

WriteSQL renders the constraint.

type Function

type Function struct{ Name string }

Function is a MySQL stored function, which returns a value and can be called in an expression. Its name is unique per schema, in a namespace separate from a Procedure's.

type Index

type Index struct{ Name string }

Index is a MySQL index, declared once. Its name is unique per table.

type IndexElement

type IndexElement interface {
	WriteIndexElement(b *strings.Builder, a *sqlb.Args)
	IndexColumns() []ddl.ColumnRef
}

IndexElement is one key part of an index.

type IndexKeyElem

type IndexKeyElem[T any] struct {
	// contains filtered or unexported fields
}

IndexKeyElem is a column, prefix or expression key part.

func IndexExpr

func IndexExpr[T any](e sqlb.Expr[T]) IndexKeyElem[T]

IndexExpr indexes an expression, a functional key part, which MySQL writes in a second pair of parentheses.

func IndexKey

func IndexKey[T any](col sqlb.Expr[T]) IndexKeyElem[T]

IndexKey indexes a column.

func IndexPrefix

func IndexPrefix[T ~string | *string](col sqlb.Expr[T], n int) IndexKeyElem[T]

IndexPrefix indexes the first n characters of a text column, which is the only way a TEXT column is indexed at all.

func (IndexKeyElem[T]) Desc

func (k IndexKeyElem[T]) Desc() IndexKeyElem[T]

Desc sorts the key part descending.

func (IndexKeyElem[T]) IndexColumns

func (k IndexKeyElem[T]) IndexColumns() []ddl.ColumnRef

IndexColumns is the column a column key part names.

func (IndexKeyElem[T]) WriteIndexElement

func (k IndexKeyElem[T]) WriteIndexElement(b *strings.Builder, a *sqlb.Args)

WriteIndexElement renders the key part, its columns bare.

type IndexMethod

type IndexMethod string

IndexMethod is BTREE or HASH; InnoDB builds BTREE whatever is asked.

The set is closed. It is a named string type, so IndexMethod("anything") compiles, and until 2026-09-24 both places that rendered one wrote it into the statement without asking — which made it an injection path, not merely a way to reach a wrong keyword. writeUsing is now the only renderer and it fails the build on a value outside the constants.

const (
	BTree IndexMethod = "BTREE"
	Hash  IndexMethod = "HASH"
)

The methods.

type IndexOption

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

IndexOption is one of MySQL's index options, which CREATE INDEX and an inline key both take. The set is closed to the four that describe the index itself; ENGINE_ATTRIBUTE and SECONDARY_ENGINE_ATTRIBUTE are left out because each is a JSON blob whose meaning belongs to a storage engine this module does not target.

func IndexComment

func IndexComment(text string) IndexOption

IndexComment attaches a comment to the index, which SHOW INDEX reports. It is the one place a reason for an index can live beside the index.

func IndexInvisible

func IndexInvisible() IndexOption

IndexInvisible creates the index hidden from the optimizer, which is how an index is added and measured before any query is allowed to depend on it. SetIndexInvisible is the ALTER TABLE counterpart.

func IndexKeyBlockSize

func IndexKeyBlockSize(kb int) IndexOption

IndexKeyBlockSize suggests the index's page size in kilobytes. InnoDB takes it only on a COMPRESSED table and warns otherwise, which is why it is an option rather than a default.

func IndexVisible

func IndexVisible() IndexOption

IndexVisible creates the index available to the optimizer, which is the default; it exists so the visibility can be written out rather than implied.

func IndexWithParser

func IndexWithParser(name string) IndexOption

IndexWithParser names the full-text parser plugin for a FULLTEXT index, the clause a language needing its own word breaking requires. MySQL refuses it on any other kind of index.

type InsertClause

type InsertClause = sqlb.Clause[Dialect, sqlb.InsertKind]

InsertClause is a clause for an INSERT on MySQL.

func InsertIgnore

func InsertIgnore() InsertClause

InsertIgnore makes the INSERT skip a row that would violate a unique key instead of failing, turning the error into a warning. It also turns other errors into warnings, a value too long for its column among them, which is why OnDuplicateKeyUpdate is the better answer when a duplicate is the only expected conflict.

func OnDuplicateKeyUpdate

func OnDuplicateKeyUpdate(first sqlb.Assignment, more ...sqlb.Assignment) InsertClause

OnDuplicateKeyUpdate is MySQL's upsert: when the row would violate a unique key, the existing row is updated with the assignments instead. It names the inserted row with a row alias, AS new, which New refers to; it targets every unique key at once, where Postgres's ON CONFLICT targets one, which is why it is here and not beside it.

type InsertQuery

type InsertQuery = sqlb.Insert[Dialect]

InsertQuery is the statement Insert returns, with no Build until a row, a query or a body completes it.

func Insert

func Insert(t sqlb.Table) *InsertQuery

Insert starts an INSERT into t for MySQL.

type InsertReady

type InsertReady = sqlb.InsertReady[Dialect]

InsertReady is a complete INSERT.

type IntervalUnit

type IntervalUnit string

IntervalUnit is the unit of an event's interval. The set is MySQL's single-field units; the compound ones (DAY_HOUR and its siblings) are absent because each takes a two-part quantity like '1:30', which is a second value syntax for one construct.

const (
	UnitSecond  IntervalUnit = "SECOND"
	UnitMinute  IntervalUnit = "MINUTE"
	UnitHour    IntervalUnit = "HOUR"
	UnitDay     IntervalUnit = "DAY"
	UnitWeek    IntervalUnit = "WEEK"
	UnitMonth   IntervalUnit = "MONTH"
	UnitQuarter IntervalUnit = "QUARTER"
	UnitYear    IntervalUnit = "YEAR"
)

The interval units.

type KeyClause

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

KeyClause is a key in CREATE TABLE: PRIMARY KEY, UNIQUE, INDEX or FULLTEXT.

func PrimaryKey

func PrimaryKey(first ddl.ColumnRef, more ...ddl.ColumnRef) KeyClause

PrimaryKey makes the table's primary key. InnoDB stores the table in its order, so a short, increasing key is the fast one. MySQL names every primary key PRIMARY, so there is no Named.

func TableFulltext

func TableFulltext(ix Index, first ddl.ColumnRef, more ...ddl.ColumnRef) KeyClause

TableFulltext makes a named FULLTEXT index inside CREATE TABLE, which Match needs over exactly these columns.

func TableIndex

func TableIndex(ix Index, first ddl.ColumnRef, more ...ddl.ColumnRef) KeyClause

TableIndex makes a named plain index inside CREATE TABLE, which MySQL allows and the other engines do not; CreateIndex is the statement form.

func TableSpatial

func TableSpatial(ix Index, first ddl.ColumnRef, more ...ddl.ColumnRef) KeyClause

TableSpatial makes a named SPATIAL index inside CREATE TABLE, over geometry columns MySQL requires to be NOT NULL.

func Unique

func Unique(c TableConstraint, first ddl.ColumnRef, more ...ddl.ColumnRef) KeyClause

Unique makes a named unique key. A TEXT or BLOB column needs a prefix length to be a key, which this does not take; the type table spells text as VARCHAR(255) for that reason.

func (KeyClause) ClauseTable

func (k KeyClause) ClauseTable() sqlb.Table

ClauseTable is a unique key's declared table, empty for the other keys.

func (KeyClause) DescribeInto

func (k KeyClause) DescribeInto(t *schema.Table)

DescribeInto sets the primary key, or adds a unique or plain index. A FULLTEXT index is not a schema.Index, which has no kind for it, so it is left out of the description.

func (KeyClause) NamedColumns

func (k KeyClause) NamedColumns() []ddl.ColumnRef

NamedColumns is the key's columns.

func (KeyClause) Position

func (KeyClause) Position() ddl.Position

Position places the key among the table's elements.

func (KeyClause) TableClauseOf

func (KeyClause) TableClauseOf(Dialect)

TableClauseOf marks the clause as MySQL's.

func (KeyClause) Using

func (k KeyClause) Using(m IndexMethod) KeyClause

Using picks the index type of an inline key. InnoDB builds a BTREE whatever is asked, so this only bites on a MEMORY table, where HASH is the default and BTREE must be asked for to get a range scan.

func (KeyClause) With

func (k KeyClause) With(first IndexOption, more ...IndexOption) KeyClause

With adds index options to an inline key; see IndexOption.

func (KeyClause) WriteSQL

func (k KeyClause) WriteSQL(b *strings.Builder, a *sqlb.Args)

WriteSQL renders the key.

type LockOption

type LockOption int

LockOption is what a locking read does when a row is already locked.

const (
	NoWait LockOption = iota + 1
	SkipLocked
)

The lock options. NoWait fails at once; SkipLocked leaves the row out, which is how a job queue hands each worker a different row.

type MatchMode

type MatchMode int

MatchMode is how a full-text search reads its query.

const (
	NaturalLanguage MatchMode = iota + 1
	Boolean
)

The modes. NaturalLanguage ranks by relevance; Boolean reads +, - and * operators in the query.

type Param

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

Param is one parameter of a stored routine: a name, a SQL type and, for a procedure, a mode. The type is a ddl.SQLType, the same value a column declaration takes, so a parameter and the column it is written to are spelled from one declaration rather than twice.

func RoutineParam

func RoutineParam[T any](name string, t ddl.SQLType[T]) Param

RoutineParam makes a parameter of the Go type T, spelled by t.

func (Param) Mode

func (p Param) Mode(m ParamMode) Param

Mode sets how the parameter passes its value. It is a procedure's only: MySQL's grammar has no mode on a function's parameter, so CreateFunction refuses one with ErrFunctionParamMode rather than rendering a parse error.

type ParamMode

type ParamMode int

ParamMode is how a procedure's parameter passes its value. A function's parameters are always IN and MySQL refuses a mode on one.

const (
	// ModeIn passes a value in, which is the default and the only mode a
	// function's parameter may have.
	ModeIn ParamMode = iota + 1
	// ModeOut passes a value back to the caller's variable.
	ModeOut
	// ModeInOut does both.
	ModeInOut
)

The parameter modes.

type PartitionDef

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

PartitionDef is one partition: a name and its bound. LessThan and LessThanMax make RANGE partitions, In makes LIST ones. A bound's values are written as literals, since no engine takes a placeholder in DDL; one value per partition column.

func In

func In(name string, values ...any) PartitionDef

In is a LIST partition holding rows whose key is one of values.

func LessThan

func LessThan(name string, values ...any) PartitionDef

LessThan is a RANGE partition holding rows below values, one per partition column.

func LessThanMax

func LessThanMax(name string) PartitionDef

LessThanMax is the last RANGE partition, holding every row the others do not.

type PartitionKey

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

PartitionKey is what a RANGE, LIST or HASH partitioning is computed from: an integer column, or one of the functions MySQL allows over a date column. It names its column, so the statement checks the column exists and the keys include it.

func PartitionOn

func PartitionOn[T integer](col sqlb.Expr[T]) PartitionKey

PartitionOn partitions by an integer column's own value.

func PartitionToDays

func PartitionToDays(col sqlb.Expr[time.Time]) PartitionKey

PartitionToDays partitions by TO_DAYS(col), the day number.

func PartitionToSeconds

func PartitionToSeconds(col sqlb.Expr[time.Time]) PartitionKey

PartitionToSeconds partitions by TO_SECONDS(col).

func PartitionYear

func PartitionYear(col sqlb.Expr[time.Time]) PartitionKey

PartitionYear partitions by YEAR(col).

type Partitioning

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

Partitioning is a PARTITION BY clause for CREATE TABLE. It goes at the option position and checks the whole table it belongs to; see the rules at the top of this file.

func PartitionByHash

func PartitionByHash(key PartitionKey, n int) Partitioning

PartitionByHash spreads rows over n partitions by a key's hash.

func PartitionByKey

func PartitionByKey(n int, first ddl.ColumnRef, more ...ddl.ColumnRef) Partitioning

PartitionByKey spreads rows over n partitions by MySQL's own hash of the columns, which takes any column type.

func PartitionByList

func PartitionByList(key PartitionKey) Partitioning

PartitionByList partitions by a key's value in a list.

func PartitionByListColumns

func PartitionByListColumns(first ddl.ColumnRef, more ...ddl.ColumnRef) Partitioning

PartitionByListColumns partitions by one or more columns' values in a list.

func PartitionByRange

func PartitionByRange(key PartitionKey) Partitioning

PartitionByRange partitions by ranges of a key. Give the partitions with With.

func PartitionByRangeColumns

func PartitionByRangeColumns(first ddl.ColumnRef, more ...ddl.ColumnRef) Partitioning

PartitionByRangeColumns partitions by ranges of one or more columns compared in order, which also takes dates and strings. Give the partitions with With, one value per column in each bound.

func (Partitioning) CheckTable

func (p Partitioning) CheckTable(t schema.Table) error

CheckTable enforces MySQL's rules on the table the partitioning belongs to: every primary and unique key includes every partition column, and there is no foreign key.

func (Partitioning) NamedColumns

func (p Partitioning) NamedColumns() []ddl.ColumnRef

NamedColumns is the partition columns, which the statement checks it defines.

func (Partitioning) OptionRank

func (Partitioning) OptionRank() ddl.OptionRank

OptionRank places PARTITION BY after every table option, which MySQL requires and which is a syntax error the other way round; the statement sorts it there whatever order the caller passed. See rankPartitioning.

func (Partitioning) Position

func (Partitioning) Position() ddl.Position

Position places the clause after the table's options.

func (Partitioning) TableClauseOf

func (Partitioning) TableClauseOf(Dialect)

TableClauseOf marks the clause as MySQL's.

func (Partitioning) With

func (p Partitioning) With(defs ...PartitionDef) Partitioning

With gives a RANGE or LIST partitioning its partitions, in order.

func (Partitioning) WriteSQL

func (p Partitioning) WriteSQL(b *strings.Builder, a *sqlb.Args)

WriteSQL renders PARTITION BY and the partition definitions.

type Placement

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

Placement is where a column goes among the table's columns. MySQL stores columns in a fixed order and reports it in SHOW CREATE TABLE and in SELECT *, so a column added at the end of one deployment and in the middle of another gives two tables that are equal in every other respect and differ in what SELECT * returns.

func After

func After[T any](col sqlb.Expr[T]) Placement

After places the column immediately after col.

func First

func First() Placement

First places the column before every other.

type Procedure

type Procedure struct{ Name string }

Procedure is a MySQL stored procedure, which is invoked by CALL and may return result sets and OUT parameters.

type RefAction

type RefAction int

RefAction is what a foreign key does when the referenced row goes. There is no SET DEFAULT: InnoDB rejects it.

const (
	RefNoAction RefAction = iota + 1
	RefRestrict
	RefCascade
	RefSetNull
)

The referential actions InnoDB accepts.

type RenameTableStatement

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

RenameTableStatement is RENAME TABLE.

func RenameTable

func RenameTable(from, to sqlb.Table) *RenameTableStatement

RenameTable renames a table, and can move it to another schema, which ALTER TABLE ... RENAME TO also does; this is the statement form.

func (*RenameTableStatement) And

And adds another rename to the same statement, which is the whole reason RENAME TABLE exists beside ALTER TABLE ... RENAME TO: MySQL performs every rename in one statement atomically and under one lock, so RenameTable(live, old).And(new, live) swaps two tables with no instant in which the name is missing. Two statements cannot do that.

func (*RenameTableStatement) Build

func (x *RenameTableStatement) Build() (ddl.Script, error)

Build renders the statement.

type RoutineCharacteristic

type RoutineCharacteristic int

RoutineCharacteristic is one of the clauses MySQL calls a routine's characteristics. The set is closed and complete for 8.4.

const (
	Deterministic RoutineCharacteristic = iota + 1
	NotDeterministic
	ContainsSQL
	NoSQL
	ReadsSQLData
	ModifiesSQLData
	SecurityDefiner
	SecurityInvoker
	LanguageSQL
)

The characteristics. Two matter beyond documentation. MySQL refuses to create a function at all, with ER_BINLOG_UNSAFE_ROUTINE, when binary logging is on and the function declares none of Deterministic, NoSQL or ReadsSQLData, unless log_bin_trust_function_creators is set — so a function meant to install anywhere declares one. And a routine declared Deterministic that is not lets the optimizer cache a call's result, which is a wrong answer rather than a slow one.

type RowConflict

type RowConflict int

RowConflict is what CREATE TABLE ... AS SELECT does with a row the new table's own unique key refuses. It matters only when the table is created with keys, which happens when the query's source columns carry them.

const (
	// ConflictIgnore skips the duplicate row and continues.
	ConflictIgnore RowConflict = iota + 1
	// ConflictReplace deletes the row already there and inserts the new one.
	ConflictReplace
)

The conflict behaviours.

type RowFormatKind

type RowFormatKind string

RowFormatKind is how InnoDB stores a row. It decides how a long VARCHAR, TEXT or BLOB value is split between the row and overflow pages, which is what the index-key length limit is measured against.

const (
	// RowFormatDynamic stores a long value entirely off-page, keeping a 20
	// byte pointer in the row. It is InnoDB's default since 5.7.9 and the one
	// that allows a 3072 byte index key.
	RowFormatDynamic RowFormatKind = "DYNAMIC"
	// RowFormatCompressed is Dynamic with the pages compressed, trading CPU
	// for disk.
	RowFormatCompressed RowFormatKind = "COMPRESSED"
	// RowFormatCompact stores the first 768 bytes of a long value in the row.
	RowFormatCompact RowFormatKind = "COMPACT"
	// RowFormatRedundant is the pre-5.0.3 format, kept for a table restored
	// from an old dump.
	RowFormatRedundant RowFormatKind = "REDUNDANT"
	// RowFormatDefault defers to innodb_default_row_format, which is what a
	// table written without the option already does; it exists so an ALTER
	// can put a table back under the server's default.
	RowFormatDefault RowFormatKind = "DEFAULT"
)

The row formats.

type Schedule

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

Schedule is when an event runs: once at a time, or every interval. It is a value, so a schedule declared once can be given to the CREATE EVENT and to a later ALTER EVENT that restores it.

func EventAfter

func EventAfter(n int64, u IntervalUnit) Schedule

EventAfter schedules the event to run once, n units from the moment the server reads the statement. It is MySQL's AT CURRENT_TIMESTAMP + INTERVAL form, and it is the one that needs no time zone: EventAt writes a timestamp, which MySQL reads in the session's zone, while this is relative to the server's own clock and cannot be shifted by an offset.

func EventAt

func EventAt(t time.Time) Schedule

EventAt schedules the event to run once, at t. MySQL drops such an event after it has run unless the event says ON COMPLETION PRESERVE, which is Completion's Preserve.

func EventEvery

func EventEvery(n int64, u IntervalUnit) Schedule

EventEvery schedules the event to run every n units, starting when it is created unless Starts says otherwise. A run that is still going when the next is due does not overlap: MySQL skips the due run.

func (Schedule) Ends

func (s Schedule) Ends(t time.Time) Schedule

Ends stops a repeating event after t, after which MySQL drops it unless it says ON COMPLETION PRESERVE.

func (Schedule) Starts

func (s Schedule) Starts(t time.Time) Schedule

Starts moves a repeating event's first run, so an hourly job can be pinned to the top of the hour rather than to the minute it was installed.

type ScheduledEventQuery

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

ScheduledEventQuery is CREATE EVENT with its schedule and no body yet, which has no Build: DO is not optional either.

func (*ScheduledEventQuery) Comment

Comment attaches a comment, which SHOW EVENTS reports.

func (*ScheduledEventQuery) Do

Do gives the body and completes the event. One step is written as the body; several are written BEGIN s1; s2; END, exactly as a trigger's are, and no client DELIMITER is involved because database/sql sends the statement whole.

func (*ScheduledEventQuery) OnCompletion

OnCompletion says what happens to the event once it has no run left.

func (*ScheduledEventQuery) Status

Status enables or disables the event.

type SelectClause

type SelectClause = sqlb.Clause[Dialect, sqlb.SelectKind]

SelectClause is a clause for a SELECT on MySQL.

func ForShare

func ForShare(opts ...LockOption) SelectClause

ForShare locks the rows read against writes by others.

func ForUpdate

func ForUpdate(opts ...LockOption) SelectClause

ForUpdate locks the rows read for writing until the transaction ends.

func ForUpdateOf

func ForUpdateOf(t sqlb.Table, opts ...LockOption) SelectClause

ForUpdateOf locks only the rows of the named tables in a join.

func WithRollup

func WithRollup() SelectClause

WithRollup adds the super-aggregate rows to a GROUP BY: one per level, with the grouping column NULL. MySQL writes it as a suffix of GROUP BY where Postgres writes ROLLUP(...) inside it, which is why each engine has its own.

type SelectQuery

type SelectQuery = sqlb.Select[Dialect]

SelectQuery is the statement type Select returns.

func Select

func Select(items ...sqlb.SQLer) *SelectQuery

Select starts a SELECT for MySQL. Items passed here carry no scan targets; a query to be scanned calls Select() and adds bindings with Columns.

type TableClause

type TableClause = ddl.TableClause[Dialect]

TableClause is a MySQL clause for CREATE TABLE.

func DefaultCharset

func DefaultCharset(charset string) TableClause

DefaultCharset sets the table's character set, utf8mb4 for all of Unicode; the older utf8 is three bytes and cannot store an emoji.

func InnoDB

func InnoDB() TableClause

InnoDB is the storage engine a library's table wants: transactional, with foreign keys and row locks. It is the server default, and writing it makes the table not depend on the server's default.

func RawTableOption

func RawTableOption(sql string) TableClause

RawTableOption is a CREATE TABLE option written out, the counterpart of RawAlter and the same escape hatch for the same set: MySQL's storage-tuning table options, which are an operator's decision rather than a schema a library ships. Nothing validates the string.

It takes the table options' rank, so a raw option is written before Partitioning wherever the caller places it: every option it can hold is a table option, and MySQL takes those in any order but only before PARTITION BY.

func RowFormat

func RowFormat(f RowFormatKind) TableClause

RowFormat sets how InnoDB stores a row of the table in CREATE TABLE.

func TableCollate

func TableCollate(collation string) TableClause

TableCollate sets the table's default collation.

func TableComment

func TableComment(text string) TableClause

TableComment attaches a comment to the table.

func TableEngine

func TableEngine(e Engine) TableClause

TableEngine sets the table's storage engine in CREATE TABLE. InnoDB is the same thing spelled for the one engine a library's table wants.

func Temporary

func Temporary() TableClause

Temporary makes the table a temporary one: visible to this connection only, dropped when it closes, and free to shadow a permanent table of the same name — which is the hazard as well as the point, since a query naming that table then reads the temporary one with nothing to say so.

It is a clause at ddl's modifier position, between CREATE and TABLE, so a temporary table takes the same columns, keys and options as any other.

type TableConstraint

type TableConstraint = ddl.TableConstraint

TableConstraint is a named constraint of one table, declared once. See ddl.TableConstraint. MySQL keeps unique keys and indexes in one namespace per table; a plain index is an Index value instead.

type TimedTriggerQuery

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

TimedTriggerQuery is CREATE TRIGGER with its timing and no body yet. MySQL has no WHEN clause, so a condition belongs in the body statement's WHERE.

func (*TimedTriggerQuery) Do

Do gives the body and completes the trigger. One step is written as the body; several are written BEGIN s1; s2; END, run in order for each row. No DELIMITER is involved: that is a command of the mysql client, and database/sql sends the statement whole, measured on MySQL 8.4.

func (*TimedTriggerQuery) Follows

func (x *TimedTriggerQuery) Follows(other Trigger) *TimedTriggerQuery

Follows makes this trigger run after other, and Precedes before it. MySQL fires several triggers of one timing and event in creation order unless one says otherwise, so a trigger added later that must run first needs this; without it the order is the order somebody happened to install them in.

func (*TimedTriggerQuery) Precedes

func (x *TimedTriggerQuery) Precedes(other Trigger) *TimedTriggerQuery

Precedes makes this trigger run before other.

type Trigger

type Trigger struct{ Name string }

Trigger is a MySQL trigger; its name is unique per schema.

type TriggerEvent

type TriggerEvent string

TriggerEvent is the one event that fires a trigger.

const (
	OnInsert TriggerEvent = "INSERT"
	OnUpdate TriggerEvent = "UPDATE"
	OnDelete TriggerEvent = "DELETE"
)

The events.

type TriggerStep

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

TriggerStep is a trigger's body statement, closed to the constructors below, each typed to a complete MySQL statement.

func StepBlock

func StepBlock(opener, closer string, inner ...TriggerStep) TriggerStep

StepBlock is raw procedural text wrapped around typed steps: the opener and the closer are the caller's words, and every statement between them is still a TriggerStep.

It exists because three StepRaw values cannot express a guarded statement, which an end-to-end task found on 2026-09-24 and no construct test could have. A body of several steps renders BEGIN s1; s2; END, so every step is separated, and a raw step that OPENS a block is not a statement: written as three steps the guard renders "IF ... THEN; SIGNAL ...; END IF" and MySQL 8.4 answers ER_PARSE_ERROR on the separator after THEN. The next person will reach for three StepRaw values exactly as that task did, so the shape is recorded here rather than in a commit message.

The separator rule is measured, not assumed, and it is not symmetric. There is NO separator after the opener, which is the bug this closes. There IS one after every inner statement including the last, because MySQL refuses "IF c THEN SET x = 1 END IF" and accepts "IF c THEN SET x = 1; END IF".

StepBlock("IF NEW.n < 0 THEN", "END IF", StepSignal(UserSQLState, "negative"))
// IF NEW.n < 0 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'negative'; END IF

This models no IF and no WHILE and is not a control-flow builder: MySQL's stored-program language stays the caller's, for the reason StepRaw gives. What it gives back is that the statements inside a block are typed rather than more string, so an INSERT in the body of a loop is checked like any other. Nothing validates the opener or the closer, so a value from outside the program must never reach either.

func StepDelete

func StepDelete(s *FilteredDelete) TriggerStep

StepDelete is a DELETE as a trigger's body.

func StepInsert

func StepInsert(s *InsertReady) TriggerStep

StepInsert is an INSERT as a trigger's body.

func StepRaw

func StepRaw(sql string) TriggerStep

StepRaw is a body statement written out, and it is the documented escape hatch for MySQL's procedural control flow: IF ... THEN ... END IF, WHILE, LOOP, REPEAT, CASE, DECLARE and a cursor.

Those are a second language, not SQL: they have their own scoping, handlers and a local variable namespace, and a builder for them would be a compiler for a language this module does not otherwise speak. Every construct here renders SQL a dialect can check; none of that machinery applies to a procedural block, so building one would give the appearance of checking without the substance. The string is written into the statement unchanged and nothing validates it, so a value from outside the program must never reach it.

A rule expressible as a statement should still be a statement: StepInsert, StepUpdate, StepDelete, StepSetNew and StepSignal cover a trigger body that needs no branch, and a branch over one statement is often a WHERE.

func StepSetNew

func StepSetNew[T any](col sqlb.Expr[T], v sqlb.Expr[T]) TriggerStep

StepSetNew assigns a value to a column of the row being written, the one thing only a BEFORE trigger can do: NEW.col is writable there and read-only in an AFTER trigger, where MySQL raises ER_TRIGGER_CANT_CHANGE_ROW rather than ignoring the assignment.

The value is an ordinary expression, so NewRow and OldRow compose into it: StepSetNew(updated, mysql.UTCNow()) stamps a row, and StepSetNew(slug, sqlb.Lower(NewRow(title))) derives one column from another. It is typed, so the value must have the column's Go type.

func StepSignal

func StepSignal(sqlState, message string) TriggerStep

StepSignal rejects the row with an error, which is how a trigger enforces a rule a CHECK constraint cannot express — one that reads another table, say. The statement aborts and, inside a transaction, the caller's rollback undoes the rest.

func StepUpdate

func StepUpdate(s *FilteredUpdate) TriggerStep

StepUpdate is an UPDATE as a trigger's body.

type TruncateStatement

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

TruncateStatement is TRUNCATE TABLE.

func Truncate

func Truncate(t sqlb.Table) *TruncateStatement

Truncate empties a table by recreating it, resetting AUTO_INCREMENT. It commits the transaction implicitly, as every MySQL DDL statement does, and is refused for a table another table's foreign key references.

func (*TruncateStatement) Build

func (x *TruncateStatement) Build() (ddl.Script, error)

Build renders the statement.

type UpdateClause

type UpdateClause = sqlb.Clause[Dialect, sqlb.UpdateKind]

UpdateClause is a clause for an UPDATE on MySQL.

func UpdateLimit

func UpdateLimit(n int64, order ...sqlb.OrderTerm) UpdateClause

UpdateLimit caps an UPDATE at n rows, in the order given, which is how a large backfill is done in batches without a key range. A single-table UPDATE only.

type UpdateQuery

type UpdateQuery = sqlb.Update[Dialect]

UpdateQuery is the statement Update returns, with no Build until Where or All says which rows.

func Update

func Update(t sqlb.Table) *UpdateQuery

Update starts an UPDATE of t for MySQL.

type View

type View struct{ Name string }

View is a MySQL view.

type ViewAlgorithmKind

type ViewAlgorithmKind string

ViewAlgorithmKind is how MySQL processes a view.

const (
	// ViewMerge rewrites a query against the view into one against its
	// tables, so the outer WHERE reaches the indexes. It is what makes a view
	// free, and MySQL cannot use it for a view with an aggregate, DISTINCT,
	// LIMIT, UNION or a window function.
	ViewMerge ViewAlgorithmKind = "MERGE"
	// ViewTemptable materialises the view into a temporary table first, which
	// has no index and is therefore the slow path — asking for it explicitly
	// is how a view is kept from being merged into a query that would lock
	// its tables for longer.
	ViewTemptable ViewAlgorithmKind = "TEMPTABLE"
	// ViewUndefined lets MySQL choose, which is the default.
	ViewUndefined ViewAlgorithmKind = "UNDEFINED"
)

The view algorithms.

type ViewSecurity

type ViewSecurity int

ViewSecurity is whose privileges MySQL checks when a view is read.

const (
	// ViewDefiner checks the view's definer, which is MySQL's default and is
	// how a view grants narrowed access to a table the reader cannot select
	// from directly.
	ViewDefiner ViewSecurity = iota + 1
	// ViewInvoker checks the reader's own privileges, so the view grants
	// nothing the reader did not already have.
	ViewInvoker
)

The security contexts.

Jump to

Keyboard shortcuts

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