sqlite

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

sqlite — SQLite statements and constructs

Everything SQLite in one import. Statements start here, sqlite.Select, sqlite.Insert, sqlite.Update and sqlite.Delete, with the dialect in their type; and every SQLite construct that goes inside them is here too: JSON1 (every function prefixed JSON, since sqlite.Insert is the statement), both upsert mechanisms, FTS5, the connection-scoped functions, and the index hints.

Every construct here is executed, not merely rendered. contrib/driver-sqlite runs all of them against a real database, which is the only reason this package can be called proven. And LIKE escaping is a capability, not a default: SQLite has no escape character at all, so a backslash-escaped pattern matches zero rows unless ESCAPE is written out — which is why expr.Contains asks the dialect first and records ErrNoLikeEscape when it declines.

Full documentation

The page for this package is docs/sqlite/README.md, with runnable snippets — every one of them copied from a test whose expected output go test checks. The documentation index is ../docs/README.md and the repository README is ../README.md.

Documentation

Overview

Package sqlite holds what only SQLite has.

It is the counterpart of pg and ch, and it exists so the three engines this repository can render for have the same shape: a dialect in the core, a construct package here, and a driver module under contrib for whoever needs to execute the result.

SQLite is the one engine whose constructs this repository can prove. The driver in contrib/driver-sqlite is pure Go and needs no server, so every helper here is executed against a real database in that module's tests, not only rendered and compared as text. No other engine package can say that yet.

Files: sqlite.go (the guarded constructors), write.go (conflict resolution), json.go (the JSON1 extension), text.go, time.go, misc.go, pragma.go (the PRAGMA statements), and the virtual tables in fts.go, rtree.go and virtual.go.

Index

Constants

This section is empty.

Variables

View Source
var (
	InsertReturning = sqlb.InsertReturning[Dialect]
	UpdateReturning = sqlb.UpdateReturning[Dialect]
	DeleteReturning = sqlb.DeleteReturning[Dialect]
)

InsertReturning, UpdateReturning and DeleteReturning add RETURNING to a complete write. They are the core's functions constrained to a dialect with the capability, instantiated for SQLite, which has had RETURNING since 3.35.

View Source
var ErrAddStored = errors.New("sqlb/sqlite: SQLite cannot add a STORED generated column")

ErrAddStored is returned for a stored generated column in ADD COLUMN, which SQLite refuses because every existing row would need computing; use GeneratedVirtual, or rebuild the table.

View Source
var ErrEmptyModifier = errors.New("sqlb/sqlite: a time modifier cannot be empty")

ErrEmptyModifier is an empty time modifier, which SQLite answers with NULL from the whole function rather than with an error.

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

ErrEmptyName is returned for an object value with no name.

View Source
var ErrIncompleteSpec = errors.New("sqlb/sqlite: a JSON pair has no value")

ErrIncompleteSpec is returned for a caller-written Pair with no Value: the type has exported fields and is written as a literal, so Pair{} is the easy mistake, and it rendered through a nil SQLer inside Build until 2026-09-22.

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

ErrMixedReferences is returned for a foreign key whose referenced columns are on more than one table.

View Source
var ErrModuleName = errors.New("sqlb/sqlite: a module name must be letters, digits and underscores")

ErrModuleName is a module name that is not a bare identifier.

The name is written into the statement verbatim, since no engine takes a placeholder there and quoting it would change which module SQLite looks for. That makes it the one piece of a virtual table that could carry text out of its position, so anything but letters, digits and underscores is refused here rather than rendered.

View Source
var ErrNegativeTimeout = errors.New("sqlb/sqlite: busy_timeout cannot be negative")

ErrNegativeTimeout is a busy timeout below zero, which SQLite reads as no wait at all rather than as the wait the caller meant.

View Source
var ErrNoModule = errors.New("sqlb/sqlite: a virtual table needs a module name")

ErrNoModule is a CREATE VIRTUAL TABLE with no module name.

View Source
var ErrPageSize = errors.New("sqlb/sqlite: page_size must be a power of two from 512 to 65536")

ErrPageSize is a page size SQLite would silently ignore: it takes a power of two from 512 to 65536 and drops anything else without an error.

View Source
var ErrRTreeDims = errors.New("sqlb/sqlite: an R*Tree has one to five dimensions")

ErrRTreeDims is an R*Tree with no dimension or more than five, the range SQLite accepts.

View Source
var ErrRebuildIncomplete = errors.New("sqlb/sqlite: a rebuild needs the old table, Into and at least one Copy")

ErrRebuildIncomplete is returned for a rebuild with no new definition or no column copied.

View Source
var ErrRebuildSameName = errors.New("sqlb/sqlite: the rebuilt table needs a name of its own until the rename")

ErrRebuildSameName is returned for a rebuild whose new table has the old one's name; the new one is created alongside and renamed into place.

View Source
var ErrTemporaryQualified = errors.New("sqlb/sqlite: a temporary object cannot name a schema other than temp")

ErrTemporaryQualified is a temporary object whose name is qualified by a schema other than temp.

SQLite refuses it: "temporary table name must be unqualified", measured on 3.50.3. A temporary object always lives in the temp schema, so naming another one is a contradiction rather than a placement, and Build says so instead of letting the engine.

View Source
var ErrTemporaryTable = errors.New("sqlb/sqlite: a temporary table cannot name a schema other than temp")

ErrTemporaryTable is a CREATE TEMP TABLE whose table names a schema other than temp, which SQLite refuses with "temporary table name must be unqualified", measured on 3.50.3.

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

ErrUnknownKeyword is returned for a value outside its named constants, such as a zero referential action or collation.

Functions

func Abs

func Abs[T sqlb.Number](e sqlb.Expr[T]) sqlb.Expr[T]

Abs renders abs(e). SQLite returns NULL rather than raising on the most negative 64-bit integer, where other engines raise.

func AutoincrementKey

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

AutoincrementKey makes col the INTEGER PRIMARY KEY with AUTOINCREMENT, so a rowid is never reused, even after the row with the largest one is deleted. It is written in the column's definition, the only place SQLite accepts it, and replaces PrimaryKey rather than joining it. Without it SQLite may reuse the largest rowid, which is the right default for almost every table.

func BM25

func BM25(table sqlb.Table, weights ...float64) sqlb.Expr[float64]

BM25 renders bm25(table), the FTS5 relevance score, optionally weighted per column. Like Rank it is negative and smaller is better.

func BinOp

func BinOp[R any](construct, op string, l, r sqlb.SQLer) sqlb.Expr[R]

BinOp renders "left op right" as a guarded expression typed R.

func BinPred

func BinPred(construct, op string, l, r sqlb.SQLer) sqlb.Predicate

BinPred renders "left op right" as a guarded predicate.

func Changes

func Changes() sqlb.Expr[int64]

Changes renders changes(), the rows modified by the most recent statement on this connection. The same pooling caveat as LastInsertRowid applies.

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 this engine and to the statement kind K, which the caller names: an extension package writing a SELECT clause instantiates ClauseIn[sqlb.SelectKind].

func ColumnCollate

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

ColumnCollate gives a text column a collation, which every comparison, index and UNIQUE on it then uses.

func Date

func Date(e sqlb.SQLer, mods ...Modifier) sqlb.Expr[string]

Date renders date(e, modifiers...), the date part as "YYYY-MM-DD".

func DateTime

func DateTime(e sqlb.SQLer, mods ...Modifier) sqlb.Expr[string]

DateTime renders datetime(e, modifiers...) as "YYYY-MM-DD HH:MM:SS". It is the closest thing SQLite has to date_trunc, through StartOfDay and friends.

func Excluded

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

Excluded references the row that would have been inserted, inside a DO UPDATE. SQLite names it excluded, as Postgres does.

func Expr

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

Expr makes a guarded typed expression from a render function.

func Format

func Format(format string, args ...sqlb.SQLer) sqlb.Expr[string]

Format renders format(fmt, args...) (3.38), printf-style formatting. The format string is an author constant.

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 every write and stored, which an index on it needs to be cheap. ADD COLUMN refuses it.

func GeneratedVirtual

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

GeneratedVirtual makes col computed by e on every read and stored nowhere. It is the one generated column ADD COLUMN accepts.

func Glob

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

Glob renders e GLOB $n, Unix shell wildcard matching. It is always case-sensitive, where LIKE is case-insensitive for ASCII by default, which is the usual reason to reach for it.

func GroupConcat

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

GroupConcat renders group_concat(e, sep). SQLite's string_agg, and not universal: Postgres spells it string_agg and the separator argument is optional here but not there.

func Guard

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

Guard reports whether rendering may continue under the dialect in a. When it returns false it has already recorded the construct as unsupported.

func Hex

func Hex(e sqlb.SQLer) sqlb.Expr[string]

Hex renders hex(e), the uppercase hexadecimal of a blob or text.

func Highlight

func Highlight(table sqlb.Table, column int, openTag, closeTag string) sqlb.Expr[string]

Highlight renders highlight(table, column, openTag, closeTag), the matched text with markers around the matching terms. The column is an index, 0-based, counting the FTS5 table's own columns.

func IIF

func IIF[T any](cond sqlb.Predicate, then, els sqlb.Expr[T]) sqlb.Expr[T]

IIF renders iif(cond, then, else) (3.32), the expression form of CASE.

func IfNull

func IfNull[T any](a, b sqlb.Expr[T]) sqlb.Expr[T]

IfNull renders ifnull(a, b), COALESCE with exactly two arguments. The core has Coalesce, which every engine spells the same; this is here because the name is not universal.

func Instr

func Instr(haystack sqlb.Expr[string], needle string) sqlb.Expr[int32]

Instr renders instr(haystack, needle): the 1-based position, or 0 when absent. SQLite's spelling of what Postgres calls strpos.

func Is

func Is(d sqlb.Dialect) bool

Is reports whether d is the SQLite dialect.

func IsEqual

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

IsEqual renders l IS r, SQLite's null-safe equality: two NULLs are equal. It is not Is, which reports whether a dialect is SQLite.

func IsNot

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

IsNot renders l IS NOT r, SQLite's null-safe inequality: true when exactly one side is NULL, where <> would be NULL. It is what a trigger's WHEN wants, OLD.status IS NOT NEW.status firing when a status becomes NULL.

func JSONArray

func JSONArray(items ...sqlb.SQLer) sqlb.Expr[string]

JSONArray renders json_array(items...).

func JSONArrayLength

func JSONArrayLength(e sqlb.Expr[string]) sqlb.Expr[int32]

JSONArrayLength renders json_array_length(e).

func JSONArrayLengthAt

func JSONArrayLengthAt(e sqlb.Expr[string], path string) sqlb.Expr[int32]

JSONArrayLengthAt renders json_array_length(e, '$.path').

func JSONArrow

func JSONArrow(e sqlb.Expr[string], path string) sqlb.Expr[string]

JSONArrow renders e -> '$.path' (3.38), which always yields JSON text. Extract is usually what you want, because it preserves the value's type.

func JSONArrowText

func JSONArrowText(e sqlb.Expr[string], path string) sqlb.Expr[string]

JSONArrowText renders e ->> '$.path' (3.38), the extracted value as SQL text. It is the same spelling Postgres uses, and it means the same thing, which is rare enough between these two engines to be worth saying.

func JSONEach

func JSONEach(e sqlb.SQLer, alias string) sqlb.Source

JSONEach renders json_each(e) as a FROM source, one row per element of an array or member of an object. The returned Source carries the alias; its columns are key, value, type, atom, id, parent, fullkey and path.

func JSONExtract

func JSONExtract[R any](e sqlb.Expr[string], path string) sqlb.Expr[R]

JSONExtract renders json_extract(e, '$.path'). It returns the value with its SQL type, so a JSON number comes back as a number rather than as text.

The path is an author constant rendered into the statement, because SQLite will not take a bound parameter where a path is expected in an expression index, and an index that does not match the query is worse than no index. A path built from request data does not belong here.

func JSONGroupArray

func JSONGroupArray(e sqlb.SQLer, opts ...sqlb.AggOption) sqlb.Expr[string]

JSONGroupArray renders json_group_array(e), the group as a JSON array. It is SQLite's json_agg, and it returns "[]" over zero rows rather than NULL, which is the opposite of what Postgres does.

func JSONGroupObject

func JSONGroupObject(key, value sqlb.SQLer, opts ...sqlb.AggOption) sqlb.Expr[string]

JSONGroupObject renders json_group_object(key, value).

func JSONInsert

func JSONInsert(e sqlb.Expr[string], path string, value sqlb.SQLer) sqlb.Expr[string]

JSONInsert renders json_insert(e, '$.path', value): creates the value only when the path is missing, and leaves an existing one alone.

func JSONObject

func JSONObject(pairs ...Pair) sqlb.Expr[string]

JSONObject renders json_object(k1, v1, k2, v2, ...) from alternating pairs. Keys are author constants; values are expressions and may bind.

func JSONPatch

func JSONPatch(target, patch sqlb.Expr[string]) sqlb.Expr[string]

JSONPatch renders json_patch(target, patch), an RFC 7386 merge patch: a null in the patch deletes the key rather than setting it to null.

func JSONQuote

func JSONQuote[T any](v T) sqlb.Expr[string]

JSONQuote renders json_quote(v), a Go value as a JSON literal. The value binds.

func JSONRemove

func JSONRemove(e sqlb.Expr[string], paths ...string) sqlb.Expr[string]

JSONRemove renders json_remove(e, '$.path', ...), dropping one or more paths.

func JSONReplace

func JSONReplace(e sqlb.Expr[string], path string, value sqlb.SQLer) sqlb.Expr[string]

JSONReplace renders json_replace(e, '$.path', value): the mirror of Insert, replacing only what is already there.

func JSONSet

func JSONSet(e sqlb.Expr[string], path string, value sqlb.SQLer) sqlb.Expr[string]

JSONSet renders json_set(e, '$.path', value): replaces the value at the path, and creates it when it is missing.

func JSONTree

func JSONTree(e sqlb.SQLer, alias string) sqlb.Source

JSONTree renders json_tree(e) as a FROM source, which walks the whole document rather than one level. Same columns as Each.

func JSONType

func JSONType(e sqlb.Expr[string]) sqlb.Expr[string]

JSONType renders json_type(e): "object", "array", "text", "integer", "real", "true", "false" or "null". Note that true and false are separate types, not one boolean, which differs from Postgres.

func JSONTypeAt

func JSONTypeAt(e sqlb.Expr[string], path string) sqlb.Expr[*string]

JSONTypeAt renders json_type(e, '$.path'), the type at a path rather than of the whole document. NULL when the path matches nothing.

func JSONValid

func JSONValid(e sqlb.Expr[string]) sqlb.Expr[bool]

JSONValid renders json_valid(e). SQLite does not validate on write, so a text column holding JSON can hold anything; this is the check a CHECK constraint or a filter uses.

func JulianDay

func JulianDay(e sqlb.SQLer, mods ...Modifier) sqlb.Expr[float64]

JulianDay renders julianday(e, modifiers...), days since noon in Greenwich on 24 November 4714 BC. Subtracting two of them is how SQLite measures an interval, since it has no interval type.

func LastInsertRowid

func LastInsertRowid() sqlb.Expr[int64]

LastInsertRowid renders last_insert_rowid(), the rowid of the most recent insert on this connection.

On this connection is the trap. database/sql hands out a pool, so a second statement can run on a different connection and see a different answer, or none. Use RETURNING instead, which SQLite has had since 3.35 and which the core exposes through the dialect's Returning capability.

func Length

func Length(e sqlb.Expr[string]) sqlb.Expr[int32]

Length renders length(e), the number of characters in a text value, which is what a CHECK on a column's length means. It is here rather than in the core because MySQL's length() counts bytes. It is int32, as Instr is, so the two compose in Substr.

func List

func List(a *sqlb.Args, items []sqlb.SQLer) string

List renders SQLers comma-separated.

func Match

func Match(e sqlb.Expr[string], query string) sqlb.Predicate

Match renders e MATCH $n, the full-text search operator.

It works only against an FTS5 or FTS4 virtual table, and the left operand is the table name rather than a column when searching every column. A MATCH against an ordinary table is an error at run time, not at Build: the builder cannot know which tables are virtual.

func Max

func Max[T any](first sqlb.Expr[T], rest ...sqlb.Expr[T]) sqlb.Expr[T]

Max renders max(a, b, ...), the scalar many-argument form, which is a different function from the aggregate of the same name. SQLite decides which by argument count; the Go name says which you asked for.

func Min

func Min[T any](first sqlb.Expr[T], rest ...sqlb.Expr[T]) sqlb.Expr[T]

Min renders min(a, b, ...), the scalar form.

func New

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

New is a column's value after the change.

func NotGlob

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

NotGlob renders e NOT GLOB $n.

func Now

func Now() sqlb.Expr[string]

Now renders the literal 'now', the argument every time function takes to mean the current instant. It is UTC unless followed by LocalTime.

func Old

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

Old is a column's value before the change, in a trigger's WHEN or body.

func Pred

func Pred(construct string, render func(a *sqlb.Args) string) sqlb.Predicate

Pred makes a guarded predicate from a render function.

func QuoteLit

func QuoteLit(s string) sqlb.SQLer

QuoteLit renders an author-chosen constant as a single-quoted literal.

func QuoteSQL

func QuoteSQL(e sqlb.SQLer) sqlb.Expr[string]

QuoteSQL renders quote(e), the value as a SQL literal. For building a statement inside SQLite itself; the builder quotes its own values.

func Raise

func Raise(action RaiseAction, message string) sqlb.Expr[any]

Raise refuses the row from inside a trigger, with a message the caller receives as the error text.

It is how a constraint that a CHECK cannot express is enforced: a BEFORE trigger with a WHEN that matches the bad row, whose body is StepSelect(Select(sqlite.Raise(...))). Measured on 3.50.3, the insert then fails with SQLITE_CONSTRAINT and the message.

RAISE is legal only inside a trigger body — SQLite answers "RAISE() may only be used within a trigger-program" anywhere else, measured — so this is the one construct here whose position is checked by the engine rather than by the type. The message is author-written text rendered as a literal, never a value from a request. The result type is any because RAISE returns nothing: it ends the statement rather than producing a value, so there is nothing to scan and nothing to compare.

func RaiseIgnore

func RaiseIgnore() sqlb.Expr[any]

RaiseIgnore abandons the rest of the trigger and the statement that fired it, without an error and without undoing anything.

It is the one RAISE form that takes no message, because nothing is reported: the row is skipped and the caller is told the statement succeeded. Measured on 3.50.3, an INSERT whose BEFORE trigger raises IGNORE returns no error and inserts no row — which is useful for a filter and dangerous for a validation, since a caller cannot tell the difference from a row that was written.

func Random

func Random() sqlb.Expr[int64]

Random renders random(), a signed 64-bit integer. Not a float in [0,1) as random() is in Postgres, which is exactly the kind of same-name difference that keeps this out of the core.

func RandomBlob

func RandomBlob(n int) sqlb.Expr[[]byte]

RandomBlob renders randomblob(n), n cryptographically random bytes.

func Rank

func Rank(table sqlb.Table) sqlb.Expr[float64]

Rank references the FTS5 rank column, which is the relevance of the current match. It is negative, and more negative is better, so ordering by it ascending puts the best match first.

func Rowid

func Rowid(t sqlb.Table) sqlb.Expr[int64]

Rowid references a table's implicit rowid column.

Every ordinary SQLite table has one unless it was declared WITHOUT ROWID. It is not stable: VACUUM can renumber it, and INSERT OR REPLACE gives the replacing row a new one. Never store it as a reference; use it for a keyset page inside one statement, where those things cannot happen.

func Snippet

func Snippet(table sqlb.Table, column int, openTag, closeTag, ellipsis string, tokens int) sqlb.Expr[string]

Snippet renders snippet(table, column, open, close, ellipsis, tokens), a short extract around the match rather than the whole column.

func Strftime

func Strftime(format string, e sqlb.SQLer, mods ...Modifier) sqlb.Expr[string]

Strftime renders strftime(format, e, modifiers...), the general formatter every other function here is a shorthand for. The format is an author constant such as "%Y-%W" for the ISO week.

func Substr

func Substr(e sqlb.Expr[string], start sqlb.Expr[int32]) sqlb.Expr[string]

Substr renders substr(e, start), the text from the 1-based position start to the end.

func SubstrN

func SubstrN(e sqlb.Expr[string], start, n sqlb.Expr[int32]) sqlb.Expr[string]

SubstrN renders substr(e, start, n), at most n characters from start.

func Time

func Time(e sqlb.SQLer, mods ...Modifier) sqlb.Expr[string]

Time renders time(e, modifiers...), the time part as "HH:MM:SS".

func TimeLit

func TimeLit(t time.Time) sqlb.Expr[string]

TimeLit binds a Go time as the ISO-8601 text SQLite compares and sorts correctly. Passing a time.Time straight through leaves the format to the driver, and drivers disagree.

func TotalChanges

func TotalChanges() sqlb.Expr[int64]

TotalChanges renders total_changes(), rows modified since the connection was opened.

func Typeof

func Typeof(e sqlb.SQLer) sqlb.Expr[string]

Typeof renders typeof(e): "null", "integer", "real", "text" or "blob".

SQLite columns have affinity rather than a type, so one column can hold values of several storage classes. This is how a query finds out which, and there is no equivalent in an engine with real column types.

func UnixEpoch

func UnixEpoch(e sqlb.SQLer, mods ...Modifier) sqlb.Expr[int64]

UnixEpoch renders unixepoch(e, modifiers...) (3.38), seconds since 1970.

func Version

func Version() sqlb.Expr[string]

Version renders sqlite_version(), the library version as text. A health check reads it; nothing should branch on it, because the shape of the string is not a contract.

Types

type AlterClause

type AlterClause = ddl.AlterClause[Dialect]

AlterClause is a SQLite ALTER TABLE action.

func AddColumn

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

AddColumn adds a column with column clauses, a collation or a virtual generated expression, under the same refusals ddl.AddColumn has on SQLite: a NOT NULL column needs a literal default, a default cannot be an expression, and a key constraint needs a unique index instead. A stored generated column is refused with ErrAddStored.

func RenameTo

func RenameTo(to sqlb.Table) AlterClause

RenameTo renames the table to to's name. It takes the new declaration, the value the queries will use.

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 SQLite.

type AlterTableReady

type AlterTableReady = ddl.AlterTableReady[Dialect]

AlterTableReady is an ALTER TABLE with at least one action.

type AutoVacuum

type AutoVacuum int

AutoVacuum is what SQLite does with the pages a DELETE or a DROP freed.

const (
	AutoVacuumNone AutoVacuum = iota + 1
	AutoVacuumFull
	AutoVacuumIncremental
)

The auto-vacuum modes. None leaves the file the size it grew to, and the free pages are reused by later writes. Full returns them to the filesystem at every commit, which costs a little on every write. Incremental keeps a list of them and returns them when the operator asks, which is the mode a library should prefer because it leaves the when to whoever runs the database.

type Collation

type Collation int

Collation is one of SQLite's built-in collations.

const (
	Binary Collation = iota + 1
	NoCase
	RTrim
)

The collations. NoCase folds ASCII letters only, which is what a case-insensitive email wants and not what a name in another script does.

type ColumnKeyClause

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

ColumnKeyClause is a column-level PRIMARY KEY, with the sort order and the conflict resolution SQLite lets it carry.

func ColumnKey

func ColumnKey[T any](col sqlb.Expr[T]) ColumnKeyClause

ColumnKey makes col the table's primary key, written in the column's own definition rather than as a table constraint.

The two spellings are not interchangeable. A single INTEGER column written as a column-level PRIMARY KEY is an alias for the rowid, SQLite's own row number, which is the cheapest key there is; the same column written as PrimaryKey(col) is too. What only this form can say is Desc and OnConflict, and Desc is the sharp one: INTEGER PRIMARY KEY DESC is explicitly NOT a rowid alias, so the column becomes an ordinary indexed column that may hold NULL. Reach for this when you want that, or when you want a conflict resolution on the key; otherwise PrimaryKey reads better.

AutoincrementKey is the other column-level key and replaces this rather than joining it: SQLite accepts AUTOINCREMENT only after a plain ascending PRIMARY KEY.

func (ColumnKeyClause) Asc

Asc keys the column ascending, the default, written out.

func (ColumnKeyClause) Desc

Desc keys the column descending, which on an INTEGER column also stops it being an alias for the rowid.

func (ColumnKeyClause) DescribeInto

func (c ColumnKeyClause) DescribeInto(t *schema.Table)

DescribeInto makes the column the primary key.

func (ColumnKeyClause) OnConflict

func (c ColumnKeyClause) OnConflict(action OrAction) ColumnKeyClause

OnConflict resolves a duplicate key by action instead of failing, which makes every INSERT into the table behave as INSERT OR <action> for this key.

func (ColumnKeyClause) Part

Part places the key where a constraint that supplies the column's value goes, the same position AUTOINCREMENT takes.

func (ColumnKeyClause) Position

func (ColumnKeyClause) Position() ddl.Position

Position marks the clause as a column clause.

func (ColumnKeyClause) TableClauseOf

func (ColumnKeyClause) TableClauseOf(Dialect)

TableClauseOf marks the clause as SQLite's.

func (ColumnKeyClause) Target

func (c ColumnKeyClause) Target() ddl.ColumnRef

Target is the column the clause belongs to.

func (ColumnKeyClause) WriteSQL

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

WriteSQL renders the key.

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 Conflict

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

Conflict accumulates an ON CONFLICT clause. Build it with OnConflict, then DoNothing or DoUpdate.

SQLite spells this exactly as Postgres does, and it is still here rather than in the core: two engines agreeing is not the rule, and MySQL spells the same idea ON DUPLICATE KEY UPDATE.

func OnConflict

func OnConflict(cols ...sqlb.SQLer) *Conflict

OnConflict targets the given columns, which must be a unique index. No columns means any conflict, which SQLite accepts only with DoNothing.

func (*Conflict) Clause

func (c *Conflict) Clause() InsertClause

Clause finishes a DoUpdate chain.

func (*Conflict) DoNothing

func (c *Conflict) DoNothing() InsertClause

DoNothing renders DO NOTHING: the conflicting row is skipped.

func (*Conflict) DoUpdate

func (c *Conflict) DoUpdate(as ...sqlb.Assignment) *Conflict

DoUpdate renders DO UPDATE SET. Use Excluded to read the row that would have been inserted.

func (*Conflict) TargetWhere

func (c *Conflict) TargetWhere(ps ...sqlb.Predicate) *Conflict

TargetWhere adds the WHERE of a partial unique index to the target, so the clause names the same index the schema declares.

func (*Conflict) UpdateWhere

func (c *Conflict) UpdateWhere(ps ...sqlb.Predicate) *Conflict

UpdateWhere adds a condition to the DO UPDATE, so a row is only modified when it is worth modifying.

type CopyPair

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

CopyPair is one column of a rebuild: the new table's column and the expression over the old table that fills it.

func CopyAs

func CopyAs[T any](to, e sqlb.Expr[T]) CopyPair

CopyAs fills a column of the new table with e, an expression of the new column's own Go type over the old table, so a type change is only writable with a conversion that produces the new type: text to integer needs a cast returning int64.

type CreateFTS5Query

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

CreateFTS5Query is CREATE VIRTUAL TABLE ... USING fts5 with no columns yet, which has no Build.

func CreateFTS5

func CreateFTS5(t sqlb.Table) *CreateFTS5Query

CreateFTS5 starts an FTS5 table t, whose columns are declared on t as for any table and queried with Match, Rank and BM25.

func (*CreateFTS5Query) Columns

func (x *CreateFTS5Query) Columns(first ddl.ColumnRef, more ...ddl.ColumnRef) *CreateFTS5Statement

Columns gives the indexed columns, at least one, declared on the FTS5 table.

func (*CreateFTS5Query) IfNotExists

func (x *CreateFTS5Query) IfNotExists() *CreateFTS5Query

IfNotExists makes creating an existing FTS5 table a no-op.

type CreateFTS5Statement

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

CreateFTS5Statement is a complete CREATE VIRTUAL TABLE ... USING fts5.

func (*CreateFTS5Statement) Build

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

Build renders the statement.

func (*CreateFTS5Statement) ExternalContent

func (x *CreateFTS5Statement) ExternalContent(content sqlb.Table, rowid ddl.ColumnRef) *CreateFTS5Statement

ExternalContent makes the index read its text from content, so the text is stored once; rowid is content's integer key, which the FTS5 rowid mirrors. The index is kept in step by triggers the author writes, or by the 'rebuild' command.

func (*CreateFTS5Statement) IfNotExists

func (x *CreateFTS5Statement) IfNotExists() *CreateFTS5Statement

IfNotExists makes creating an existing FTS5 table a no-op.

func (*CreateFTS5Statement) Prefix

func (x *CreateFTS5Statement) Prefix(lengths ...int) *CreateFTS5Statement

Prefix adds prefix indexes of the given lengths, which make a prefix query ("abc*") fast.

func (*CreateFTS5Statement) Tokenize

Tokenize picks the tokenizer.

type CreateIndexQuery

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

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

func CreateIndex

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

CreateIndex starts an index ix on table t.

func (*CreateIndexQuery) IfNotExists

func (x *CreateIndexQuery) IfNotExists() *CreateIndexQuery

IfNotExists makes creating an existing index a no-op; it checks the name.

func (*CreateIndexQuery) On

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

func (*CreateIndexQuery) Unique

func (x *CreateIndexQuery) Unique() *CreateIndexQuery

Unique makes the index refuse duplicate keys.

type CreateIndexReady

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

CreateIndexReady is a CREATE INDEX with at least one key.

func (*CreateIndexReady) Build

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

Build renders the statement.

func (*CreateIndexReady) IfNotExists

func (x *CreateIndexReady) IfNotExists() *CreateIndexReady

IfNotExists makes creating an existing index a no-op.

func (*CreateIndexReady) Unique

func (x *CreateIndexReady) Unique() *CreateIndexReady

Unique makes the index refuse duplicate keys.

func (*CreateIndexReady) Where

Where makes the index partial: only rows matching p are indexed.

type CreateRTreeQuery

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

CreateRTreeQuery is CREATE VIRTUAL TABLE ... USING rtree with no columns yet, which has no Build.

func CreateRTree

func CreateRTree(t sqlb.Table) *CreateRTreeQuery

CreateRTree starts an R*Tree table t, whose columns are declared on t as for any table.

func (*CreateRTreeQuery) Columns

func (x *CreateRTreeQuery) Columns(id sqlb.Expr[int64], first Dim, more ...Dim) *CreateRTreeStatement

Columns gives the id and the dimensions, in order.

func (*CreateRTreeQuery) IfNotExists

func (x *CreateRTreeQuery) IfNotExists() *CreateRTreeQuery

IfNotExists makes creating an existing R*Tree a no-op.

func (*CreateRTreeQuery) Integer

func (x *CreateRTreeQuery) Integer() *CreateRTreeQuery

Integer stores the coordinates as 32-bit integers, rtree_i32, for grid data where float rounding would misplace a box.

type CreateRTreeStatement

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

CreateRTreeStatement is a complete CREATE VIRTUAL TABLE ... USING rtree.

func (*CreateRTreeStatement) Build

func (x *CreateRTreeStatement) 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 each column's name and type from the select list and filling the table in the same statement. It is how a staging copy or a backfill is made in one pass.

**The new table keeps none of the source's constraints**, and that is the warning worth reading twice rather than a footnote. Measured on 3.50.3 against a source declared `id INTEGER PRIMARY KEY, name TEXT NOT NULL`, the copy comes out `id INT, name TEXT`: the primary key is gone, the NOT NULL is gone, and the type is SQLite's reading of the expression rather than the declaration. A column computed by an expression gets no declared type at all, so it has blob affinity and will hold whatever it is given. A table whose shape matters is created by CreateTable, which declares it, and filled by an INSERT from a SELECT.

There are no table options here and no column list, because SQLite has neither on this form: WITHOUT ROWID is a syntax error after a select, and a column list is a syntax error before the AS. Beware that STRICT is *not* refused — it parses as an alias for the last table in the select, so it silently does nothing, which is why it is not offered.

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, because "create it and fill it" is one statement here and a second run appending its rows again would be the difference between a repeatable install and one that doubles its data.

func (*CreateTableAsStatement) Temporary

Temporary makes the new table a temporary one, in the temp schema and gone when the connection closes; see Temporary for the pooling warning that comes with every temporary object. A table naming a schema other than temp fails Build with ErrTemporaryTable, as the engine does.

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 SQLite.

type CreateTableReady

type CreateTableReady = ddl.CreateTableReady[Dialect]

CreateTableReady is a CREATE TABLE with at least one column, the only form with Build.

type CreateTriggerQuery

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

CreateTriggerQuery is CREATE TRIGGER with no timing yet, which has no Build.

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.

func (*CreateTriggerQuery) IfNotExists

func (x *CreateTriggerQuery) IfNotExists() *CreateTriggerQuery

IfNotExists makes creating an existing trigger a no-op.

func (*CreateTriggerQuery) InsteadOf

InsteadOf replaces the change on a view, which is how a view is made writable.

func (*CreateTriggerQuery) Temporary

func (x *CreateTriggerQuery) Temporary() *CreateTriggerQuery

Temporary makes the trigger live in the temp schema and vanish when the connection closes.

A temporary trigger is the only kind that may fire on a table in another database, and the only kind that survives its table being dropped without being dropped with it. It carries the pooling warning CreateViewStatement.Temporary describes: with database/sql the next statement may run on a connection that has never seen it. A Trigger naming a schema other than temp fails Build with ErrTemporaryQualified.

type CreateTriggerStatement

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

CreateTriggerStatement is a complete CREATE TRIGGER. SQLite triggers are always row-level, so FOR EACH ROW is written and there is no statement form.

func (*CreateTriggerStatement) Build

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

Build renders the statement. The body's statements render inline, so their bound values are literals.

type CreateViewQuery

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

CreateViewQuery is CREATE VIEW with no body yet, which has no Build. There is no OrReplace: CREATE OR REPLACE VIEW is a syntax error in SQLite, so replacing a view is DropView then CreateView.

func CreateView

func CreateView(v View) *CreateViewQuery

CreateView starts a view.

func (*CreateViewQuery) As

As gives the body, a SQLite SELECT from the query builder, rendered with its bound values as literals.

func (*CreateViewQuery) Columns

func (x *CreateViewQuery) Columns(first ddl.ColumnRef, more ...ddl.ColumnRef) *CreateViewQuery

Columns names the view's columns, overriding the names the body's result would otherwise get.

The columns are declared on a table of the view's own name, which is how a consumer reads the view afterwards, so the same Col values that name the columns here are the ones every query against the view uses: a view cannot be created under one column name and read under another. SQLite's own documentation recommends always naming them, because the rules by which it derives a name from a result expression are undefined and may change.

func (*CreateViewQuery) IfNotExists

func (x *CreateViewQuery) IfNotExists() *CreateViewQuery

IfNotExists makes creating an existing view a no-op.

func (*CreateViewQuery) Temporary

func (x *CreateViewQuery) Temporary() *CreateViewQuery

Temporary makes the view live in the temp schema and vanish when the connection closes. See CreateViewStatement.Temporary for the warning that comes with it.

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) Columns

func (x *CreateViewStatement) Columns(first ddl.ColumnRef, more ...ddl.ColumnRef) *CreateViewStatement

Columns names the view's columns; see CreateViewQuery.Columns.

func (*CreateViewStatement) IfNotExists

func (x *CreateViewStatement) IfNotExists() *CreateViewStatement

IfNotExists makes creating an existing view a no-op.

func (*CreateViewStatement) Temporary

func (x *CreateViewStatement) Temporary() *CreateViewStatement

Temporary makes the view live in the temp schema and vanish when the connection closes.

With database/sql that is a sharper edge than it looks: the pool hands out connections, so a temporary object created by one statement is invisible to the next unless both run on the same connection. Create it inside a transaction, or on a connection taken with Conn, or not at all. A temporary view whose View names a schema other than temp fails Build with ErrTemporaryQualified, which is what SQLite does.

type CreateVirtualTableStatement

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

CreateVirtualTableStatement is a complete CREATE VIRTUAL TABLE for a module this package has no builder for, or for geopoly.

func CreateGeopoly

func CreateGeopoly(t sqlb.Table, cols ...ddl.ColumnRef) *CreateVirtualTableStatement

CreateGeopoly creates a geopoly table: SQLite's polygon index, which answers "which shapes contain this point" and "which overlap this box" without scanning.

The columns are the table's own, declared on t as for any table, and each is checked to belong to it. They are the extra columns stored beside the shape; geopoly adds the hidden _shape column itself, which holds the polygon and is read and written through the geopoly_* functions rather than declared here. A geopoly table with no extra columns at all is legal and measured.

The module is compiled into the modernc driver contrib/driver-sqlite uses; with another build, check it is there, as CREATE VIRTUAL TABLE fails with "no such module: geopoly" when it is not.

func CreateVirtualTable

func CreateVirtualTable(t sqlb.Table, m Module, args ...string) *CreateVirtualTableStatement

CreateVirtualTable creates table t with module m and the arguments args.

The arguments are the module's own language and are not checked, not quoted and not escaped: SQLite passes the text between the parentheses to the module, which may read it as column declarations (fts5), as coordinates (rtree), as a filename, or as anything else it chose. They are written out exactly as given, joined with commas, and they are authored text like every other value in ddl — never a value that came from a request, which is the one thing that cannot be made safe here.

With no arguments the statement is USING m with no parentheses, which is the form SQLite's own documentation writes for a module that takes none; measured, USING m() is accepted too.

Prefer CreateFTS5, CreateRTree and CreateGeopoly where they apply. This is the escape hatch for the rest, including a module loaded at run time, and it exists so that a module nobody here has heard of does not mean giving up the builder and writing the whole statement as a string.

func (*CreateVirtualTableStatement) Build

Build renders the statement.

func (*CreateVirtualTableStatement) IfNotExists

IfNotExists makes creating an existing virtual table a no-op.

type Deferrability

type Deferrability int

Deferrability is when SQLite checks a foreign key.

const (
	NotDeferrable Deferrability = iota + 1
	DeferrableInitiallyDeferred
	DeferrableInitiallyImmediate
)

The deferrability settings.

Only DeferrableInitiallyDeferred changes anything: it moves the check to COMMIT, so a batch may leave a reference dangling in the middle and repair it before the end. NotDeferrable is the default and DeferrableInitiallyImmediate means the same thing at run time — the constraint is checked at the end of each statement either way. They are here because the spelling is recorded in the schema and read back by anything that reads sqlite_schema, so a schema that means to say "immediate on purpose" can say it.

type DeleteClause

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

DeleteClause is a clause for a DELETE on this engine.

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 SQLite.

type Dialect

type Dialect = sqlite.Dialect

Dialect is the SQLite dialect, re-exported so a caller that already imports this package for its constructs does not need a second import to name the engine. The definition lives in github.com/ubgo/sqlb/dialect/sqlite, which imports the render layer and nothing else.

type Dim

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

Dim is one R*Tree dimension: the columns holding its minimum and maximum.

func Dimension

func Dimension[T float32 | float64 | int32 | int64](lo, hi sqlb.Expr[T]) Dim

Dimension pairs a dimension's minimum and maximum columns. R*Tree stores coordinates as 32-bit floats; RTree's Integer stores them as 32-bit integers, and either way the Go type of a coordinate column is a float or an integer.

type DropStatement

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

DropStatement is DROP INDEX, DROP VIEW or DROP TRIGGER, with IF EXISTS. Each takes the object value, so the schema it was declared with is the schema it is dropped from and the two cannot drift apart.

func DropIndex

func DropIndex(ix Index) *DropStatement

DropIndex drops an index.

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 SQLite, one statement per table.

type FilteredDelete

type FilteredDelete = sqlb.FilteredDelete[Dialect]

FilteredDelete is a DELETE that has said which rows, the only form with Build.

type FilteredUpdate

type FilteredUpdate = sqlb.FilteredUpdate[Dialect]

FilteredUpdate is an UPDATE that has said which rows, the only form with Build.

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 from one or more pairs on one table.

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) Deferrable

Deferrable sets when the constraint is checked.

Deferring needs PRAGMA defer_foreign_keys or a DEFERRABLE INITIALLY DEFERRED key AND foreign-key enforcement on; with enforcement off nothing is checked at either time.

func (ForeignKeyClause) Deferred

func (f ForeignKeyClause) Deferred() ForeignKeyClause

Deferred checks the constraint at COMMIT rather than per statement. It is the shorthand for Deferrable(DeferrableInitiallyDeferred), the one setting that changes behaviour.

func (ForeignKeyClause) DescribeInto

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

DescribeInto adds the foreign key. SQLite's references name a table in the same database, so the reference has no schema.

func (ForeignKeyClause) NamedColumns

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

NamedColumns is the constraint's local columns.

func (ForeignKeyClause) OnDelete

OnDelete says what happens to this row when the referenced one 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 SQLite's.

func (ForeignKeyClause) WriteSQL

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

WriteSQL renders the constraint.

type Index

type Index struct{ Name, Schema string }

Index is a SQLite index, declared once as a value.

Schema names the database the index is created in, empty for main. It is the index that is qualified and never the table: SQLite requires an index and its table to be in the same schema, so CREATE INDEX writes the table unqualified. There is no TEMP form — CREATE TEMP INDEX is a syntax error, measured on 3.50.3 — and a temporary index is written by giving the index the temp schema instead.

type IndexElement

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

IndexElement is one key of an index: a column or an expression, with its sort order and collation.

type IndexKeyElem

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

IndexKeyElem is a column or expression key.

func IndexExpr

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

IndexExpr indexes an expression; a query uses it only when it filters on the same expression.

func IndexKey

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

IndexKey indexes a column.

func (IndexKeyElem[T]) Asc

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

Asc sorts the key ascending, the default, written out.

func (IndexKeyElem[T]) Collate

func (k IndexKeyElem[T]) Collate(c Collation) IndexKeyElem[T]

Collate indexes the key under a collation, which a query must use too for the index to serve it.

func (IndexKeyElem[T]) Desc

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

Desc sorts the key descending.

func (IndexKeyElem[T]) IndexColumns

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

IndexColumns is the column a column key names.

func (IndexKeyElem[T]) WriteIndexElement

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

WriteIndexElement renders the key, its columns bare.

type InsertClause

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

InsertClause is a clause for an INSERT on this engine.

func InsertOr

func InsertOr(action OrAction) InsertClause

InsertOr renders INSERT OR <action> INTO, the clause between the keyword and the table.

Prefer OnConflict where it fits. OR IGNORE hides every constraint violation including the ones that are bugs, and OR REPLACE changes the rowid, which silently breaks anything referencing the row by it.

type InsertQuery

type InsertQuery = sqlb.Insert[Dialect]

InsertQuery is the statement Insert returns. It has 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 SQLite.

type InsertReady

type InsertReady = sqlb.InsertReady[Dialect]

InsertReady is a complete INSERT, the only form with Build.

type JournalMode

type JournalMode int

JournalMode is how SQLite journals a transaction, which decides what happens to a database when the process dies mid-write.

const (
	JournalDelete JournalMode = iota + 1
	JournalTruncate
	JournalPersist
	JournalMemory
	JournalWAL
	JournalOff
)

The journal modes. WAL is the one to want for anything concurrent: readers run while a writer commits, where every other mode blocks them. It is also the only one stored in the database file rather than per connection, so setting it once is permanent, and the only one that does not work on a database opened over a network filesystem or held in memory.

type KeyClause

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

KeyClause is a PRIMARY KEY or UNIQUE table constraint.

func PrimaryKey

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

PrimaryKey makes the table's primary key. A single INTEGER column as the key is the rowid alias, SQLite's own row number, which is why an int64 id needs nothing else; AutoincrementKey is for when rowids must never be reused.

func PrimaryKeyOn

func PrimaryKeyOn(first KeyColumn, more ...KeyColumn) KeyClause

PrimaryKeyOn makes the table's primary key over decorated key columns, for a key that needs a collation or a sort order; PrimaryKey is the plain form.

func Unique

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

Unique makes a unique constraint over one or more columns.

func UniqueOn

func UniqueOn(first KeyColumn, more ...KeyColumn) KeyClause

UniqueOn makes a unique constraint over decorated key columns. A case-insensitive unique column is UniqueOn(Key(email).Collate(NoCase)).

func (KeyClause) ClauseTable

func (k KeyClause) ClauseTable() sqlb.Table

ClauseTable is the key's declared table, empty for an unnamed key.

func (KeyClause) DescribeInto

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

DescribeInto sets the primary key or adds the unique index.

func (KeyClause) Named

func (k KeyClause) Named(c TableConstraint) KeyClause

Named gives the constraint a name.

func (KeyClause) NamedColumns

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

NamedColumns is the constraint's columns.

func (KeyClause) OnConflict

func (k KeyClause) OnConflict(action OrAction) KeyClause

OnConflict makes a violation of this constraint resolve by action instead of failing. It is SQLite's own and has no equivalent elsewhere: a key that ignores duplicates makes every INSERT into the table an INSERT OR IGNORE.

func (KeyClause) Position

func (KeyClause) Position() ddl.Position

Position places the constraint among the table's elements.

func (KeyClause) TableClauseOf

func (KeyClause) TableClauseOf(Dialect)

TableClauseOf marks the clause as SQLite's.

func (KeyClause) WriteSQL

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

WriteSQL renders the constraint.

type KeyColumn

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

KeyColumn is one column of a table-level key, with the collation and sort order SQLite indexes it under.

A key is an index, so the same two decorations a CREATE INDEX key takes apply here, and they are not cosmetic: UNIQUE(email COLLATE NOCASE) is a different constraint from UNIQUE(email), and it is the one a library that stores email addresses means. Without it the uniqueness is byte-exact and two addresses differing only in case both fit.

func Key

func Key(col ddl.ColumnRef) KeyColumn

Key makes one column of a key, undecorated.

func (KeyColumn) Asc

func (k KeyColumn) Asc() KeyColumn

Asc indexes the column ascending, the default, written out.

func (KeyColumn) Collate

func (k KeyColumn) Collate(c Collation) KeyColumn

Collate indexes the key column under a collation, which a query must use too for the key's index to serve it.

func (KeyColumn) Desc

func (k KeyColumn) Desc() KeyColumn

Desc indexes the column descending. On a single INTEGER PRIMARY KEY this also stops the column being an alias for the rowid, which is a change of storage rather than of order.

type Modifier

type Modifier string

Modifier is a SQLite time modifier such as "+1 day", "start of month" or "utc". They apply left to right, so order changes the answer.

The type is a string rather than a closed set because it cannot be closed: an offset carries its number inside the string, so "+1 day", "-7 days" and "+1.5 seconds" are all modifiers and no enumeration covers them. Every modifier is written through the dialect as a LITERAL, so a value from anywhere reaches SQLite as one argument and cannot leave its position; that is the property an open type has to have.

**What it cannot protect you from is a modifier SQLite does not recognise, because SQLite does not report one.** Measured on 3.50.3: date('2020-03-15', '+1 banana') returns NULL, and so does 'start of week', and so does the empty string. Not an error — NULL, from the whole function, silently. So the parts of the vocabulary that ARE closed are closed here: Offset takes a Unit rather than a string, which turns a misspelled unit from a NULL at run time into a compile error, and an empty Modifier is refused at Build. Anything else you spell yourself is on you, and a NULL result is the symptom to look for.

const (
	StartOfDay   Modifier = "start of day"
	StartOfMonth Modifier = "start of month"
	StartOfYear  Modifier = "start of year"
	UTC          Modifier = "utc"
	LocalTime    Modifier = "localtime"
	Unixepoch    Modifier = "unixepoch"
	JulianDayMod Modifier = "julianday"
	Auto         Modifier = "auto"
	// Subsec keeps fractional seconds in the result, which the other
	// functions truncate away.
	Subsec Modifier = "subsec"
	// Ceiling and Floor decide how a month-or-year offset lands on a day the
	// target month does not have: 31 January plus one month is 2 March under
	// Ceiling and 28 February under Floor.
	Ceiling Modifier = "ceiling"
	Floor   Modifier = "floor"
)

The modifiers with fixed spellings. An offset such as "+1 day" is written by Offset, because its value is part of the string.

Note the absence of a "start of week": SQLite has no such modifier, and writing one returns NULL rather than an error. Weekday is how the same question is asked.

func Offset

func Offset(n int, unit Unit) Modifier

Offset is a relative time modifier: Offset(-7, Day) is "-7 days".

The unit is a closed set rather than a string, and that is the whole point of the type. SQLite does not refuse a unit it does not know — the function returns NULL, silently, measured — so Offset(1, "fortnights"), or a misspelling of a real unit, would have been a run-time NULL in a date somebody reads months later. As a Unit neither compiles. An unrecognised value reaching here anyway, through a conversion, renders a modifier that fails at Build.

func Weekday

func Weekday(n int) Modifier

Weekday moves forward to the next date whose day of the week is n, 0 for Sunday through 6 for Saturday, and does nothing when the date already is that day. It is how "the start of this week" is asked for, since SQLite has no start-of-week modifier.

type Module

type Module string

Module is the name of a SQLite virtual-table module.

It is a named type with constants for the modules SQLite ships, and still a string underneath, because the set cannot be closed: a module can be compiled in or loaded at run time, so an exhaustive list would be a claim about somebody else's build. What the type buys is that the module name and its arguments cannot be confused for one another at a call site.

const (
	ModuleFTS5     Module = "fts5"
	ModuleRTree    Module = "rtree"
	ModuleRTreeI32 Module = "rtree_i32"
	ModuleGeopoly  Module = "geopoly"
	ModuleDBStat   Module = "dbstat"
)

The modules built into a stock SQLite. ModuleFTS5, ModuleRTree and ModuleRTreeI32 have typed builders in this package and are named here only for the reader; reaching for them through CreateVirtualTable gives up the checking those builders do.

type NotNullConflictClause

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

NotNullConflictClause resolves a NOT NULL violation by an action instead of failing.

func NotNullOnConflict

func NotNullOnConflict[T any](col sqlb.Expr[T], action OrAction) NotNullConflictClause

NotNullOnConflict says what SQLite does with a row that leaves col null, instead of refusing it.

It is the one conflict clause in a column's definition that does anything, and what it does is measured rather than read, on 3.50.3 against a column declared NOT NULL with a default:

  • OrReplace writes the column's DEFAULT and keeps the row, which is the reason to reach for this at all: a column that is never null in the table but may be absent from a write.
  • OrIgnore skips the whole row and reports success, so a caller cannot tell it from a row that was written.
  • OrAbort, OrFail and OrRollback all fail the insert, as the plain NOT NULL does; they differ only in how much they undo.

**OrReplace needs a default**, and Build refuses one without it with ddl.ErrNoDefault. Without a default there is nothing to write in place of the null, and SQLite falls back to ABORT — measured on 3.50.3, where CREATE TABLE accepts the definition and only the first NULL written fails. That is why it is refused at Build rather than documented: the schema installs cleanly and the failure arrives later, in production. The clause declares the need through ddl.DefaultRequirer; ddl, which holds the column definition, makes the check.

The clause renders immediately after NOT NULL, at ddl.PartAfterNotNull, because that is the only position SQLite accepts: written after the DEFAULT instead, the statement is a syntax error. On a column whose definition writes no NOT NULL — a nullable one, or a generated one — Build fails with ddl.ErrNoNotNull rather than rendering a bare ON CONFLICT, which SQLite would read as a constraint of its own.

func (NotNullConflictClause) Part

Part places the clause immediately after the column's NOT NULL.

func (NotNullConflictClause) Position

func (NotNullConflictClause) Position() ddl.Position

Position marks the clause as a column clause.

func (NotNullConflictClause) RequiresDefault

func (c NotNullConflictClause) RequiresDefault() bool

RequiresDefault reports that OrReplace writes the column's default in place of a NULL, so ddl refuses it on a column that declares none. The other four actions refuse or skip the row and never write the default.

func (NotNullConflictClause) TableClauseOf

func (NotNullConflictClause) TableClauseOf(Dialect)

TableClauseOf marks the clause as SQLite's.

func (NotNullConflictClause) Target

func (c NotNullConflictClause) Target() ddl.ColumnRef

Target is the column the clause belongs to.

func (NotNullConflictClause) WriteSQL

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

WriteSQL renders the clause.

type OrAction

type OrAction string

OrAction is the conflict-resolution algorithm of an INSERT OR clause.

const (
	OrRollback OrAction = "ROLLBACK"
	OrAbort    OrAction = "ABORT"
	OrFail     OrAction = "FAIL"
	OrIgnore   OrAction = "IGNORE"
	OrReplace  OrAction = "REPLACE"
)

The five algorithms SQLite accepts, in the order the documentation lists them. ROLLBACK aborts the whole transaction; ABORT aborts the statement and keeps earlier changes; FAIL stops at the failing row and keeps the rows already inserted; IGNORE skips the row and carries on; REPLACE deletes the conflicting row first.

type Pair

type Pair struct {
	Key   string
	Value sqlb.SQLer
}

Pair is one key and value for Object. The key is an author constant, which is what keeps request data out of the JSON structure rather than only out of its values.

func KV

func KV(key string, value sqlb.SQLer) Pair

KV builds a Pair.

type PragmaStatement

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

PragmaStatement is a PRAGMA: one that sets a value, or one of the three checks that report a damaged database by returning rows.

It is one type for every pragma this package writes so that a pragma is a value a caller can hold, pass and put in a migration Script beside the DDL, and so that adding one is a constructor rather than a builder. The zero value carries no name and Build refuses it.

func DeferForeignKeys

func DeferForeignKeys(on bool) *PragmaStatement

DeferForeignKeys holds foreign-key enforcement until the transaction commits, so a batch of statements may leave a reference dangling in the middle and repair it before the end.

It is the one pragma here that is not marked OutsideTransaction, and deliberately so: SQLite clears it at every commit or rollback, measured, so setting it outside a transaction changes nothing that survives to the transaction it was meant for. It is a weaker tool than ForeignKeys(false): the constraints are still checked, only later, so a rebuild that genuinely cannot satisfy them at the end needs the enforcement off instead.

func ForeignKeyCheck

func ForeignKeyCheck() *PragmaStatement

ForeignKeyCheck reports every row whose foreign key points at a row that is not there, one row per violation and nothing at all when the references are sound.

It is the check a table rebuild ends with, and it is the reason ddl.Statement has MustReturnNoRows: this pragma reports a broken reference by returning a row rather than by failing, so a runner that only executes it reports success whatever it found.

func ForeignKeyCheckOf

func ForeignKeyCheckOf(t sqlb.Table) *PragmaStatement

ForeignKeyCheckOf reports every row of one table whose foreign key points at a row that is not there.

One table rather than the database is the useful scope for a rebuild: the rebuild changed one table, and checking the rest is reading a whole database to learn nothing about the change.

func ForeignKeys

func ForeignKeys(on bool) *PragmaStatement

ForeignKeys turns foreign-key enforcement on or off for the connection. It is a silent no-op inside a transaction, which is how a rebuild wrapped in one quietly loses its guard, so the Statement is marked OutsideTransaction and a runner must execute it before BEGIN.

func IntegrityCheck

func IntegrityCheck() *PragmaStatement

IntegrityCheck verifies the whole database: every page, every index entry against its table, every NOT NULL and every UNIQUE.

It builds as a SELECT over SQLite's pragma_integrity_check table-valued function with the 'ok' row filtered away, rather than as the bare PRAGMA, and the reason is the Statement flag it needs. A check is only a check if a runner can tell a healthy answer from a damaged one; integrity_check always returns rows, the single row 'ok' when it found nothing, so MustReturnNoRows over the bare pragma would fail every healthy database. Filtering 'ok' away makes no rows mean nothing wrong, which is what the flag says.

It reads every page, so it costs a full scan of the file. QuickCheck is the one to run routinely.

func IntegrityCheckOf

func IntegrityCheckOf(t sqlb.Table) *PragmaStatement

IntegrityCheckOf is IntegrityCheck over one table rather than the whole database: its rows, its indexes and the constraints between them.

It is the form a library that owns a few tables in somebody else's database wants, because the whole-database check reads every page of every table, including tables this library did not write and cannot repair. The table's schema qualifies the pragma where it declares one.

The N argument SQLite also accepts, a cap on how many errors are listed, is not offered: measured on 3.50.3, the table-valued form these build on reads any argument as a table name and answers "no such table: 5", and a cap is meaningless under MustReturnNoRows, which asks only whether there is one error rather than how many.

func LegacyAlterTable

func LegacyAlterTable(on bool) *PragmaStatement

LegacyAlterTable makes ALTER TABLE ... RENAME TO behave as it did before SQLite 3.25: it renames the table and does not rewrite the references to it in other tables' foreign keys, triggers and views.

It exists because the modern behaviour is what a table rebuild has to avoid. The rebuild in this package creates a new table under its own name and renames it into place at the end; with references rewritten, that rename would follow every foreign key pointing at the old table over to the new one before the old one is gone. Anything else should leave it off: a rename that quietly leaves stale references behind is a schema that fails later and far from the cause.

func QuickCheck

func QuickCheck() *PragmaStatement

QuickCheck is IntegrityCheck without the index-against-table comparison, which is most of the cost. It finds a corrupt page and misses an index that disagrees with its table.

func QuickCheckOf

func QuickCheckOf(t sqlb.Table) *PragmaStatement

QuickCheckOf is QuickCheck over one table; see IntegrityCheckOf.

func RecursiveTriggers

func RecursiveTriggers(on bool) *PragmaStatement

RecursiveTriggers turns recursive trigger firing on or off.

SQLite leaves it off for backwards compatibility, which is a trap for a schema whose triggers are written expecting the ordinary meaning: a trigger whose body changes a table with a trigger of its own does not fire the second one, silently, so half the intended work never happens. A library that ships such triggers sets this on and says so.

func SetApplicationID

func SetApplicationID(n int32) *PragmaStatement

SetApplicationID sets PRAGMA application_id, an integer in the database header that says which application a file belongs to, the way a file format's magic number does. SetUserVersion is its counterpart for the schema's version.

func SetAutoVacuum

func SetAutoVacuum(v AutoVacuum) *PragmaStatement

SetAutoVacuum sets PRAGMA auto_vacuum.

It is stored in the database file and can only be changed for free before the first table is created. Afterwards the statement is accepted, changes nothing and reports nothing, measured on 3.50.3, until a VACUUM rewrites the file; so it is marked OutsideTransaction, because that VACUUM cannot run inside a transaction and a caller who has to follow this statement with one must be able to.

func SetBusyTimeout

func SetBusyTimeout(d time.Duration) *PragmaStatement

SetBusyTimeout sets PRAGMA busy_timeout: how long a statement waits for a lock another connection holds before it gives up with SQLITE_BUSY.

The default is zero, which is why SQLITE_BUSY is the error everyone meets first: with no wait at all, two connections writing at the same instant is enough. The duration is rounded down to whole milliseconds, which is the unit SQLite takes. A negative duration is refused rather than rendered, because SQLite reads a negative value as no wait at all, which is the opposite of what writing one could mean.

func SetCacheSizeKibibytes

func SetCacheSizeKibibytes(kib uint32) *PragmaStatement

SetCacheSizeKibibytes sets PRAGMA cache_size as an amount of memory.

SQLite spells this as a negative number of kibibytes, which is the detail this constructor exists to keep out of a call site: a caller who writes the number without the sign asks for that many pages instead, silently, and on a 4 KiB page that is four times the memory they meant.

func SetCacheSizePages

func SetCacheSizePages(pages uint32) *PragmaStatement

SetCacheSizePages sets PRAGMA cache_size as a number of database pages, which is what a positive value means to SQLite.

Pages, not bytes: the memory this reserves is pages times the page size, so the same number means a different amount of memory on a database built with a different page size. SetCacheSizeKibibytes is the form that does not depend on it, and is the one to prefer when the number came from a memory budget rather than from measuring this database.

func SetJournalMode

func SetJournalMode(m JournalMode) *PragmaStatement

SetJournalMode sets PRAGMA journal_mode.

The statement is marked OutsideTransaction, and both halves of the measurement say why. Inside a transaction that has not written, SQLite raises "cannot change out of wal mode from within a transaction", so a runner batching it with a migration would fail the migration for the ordering rather than for the schema. Inside one that has written it returns no error and leaves the mode alone, which is the silent half and the reason a flag is better than a comment. Both measured on 3.50.3.

JournalOff means a crash mid-write leaves a corrupt database, so it belongs to a throwaway file and nothing else.

func SetMmapSize

func SetMmapSize(bytes uint64) *PragmaStatement

SetMmapSize sets PRAGMA mmap_size, the most of the database file SQLite may read through a memory mapping instead of through read calls. Zero turns mapping off.

It is a ceiling, not a reservation: SQLite maps up to this much and no more, so a value larger than the file costs nothing. A mapping makes an I/O error in the file arrive as a signal rather than as an error return, which is the reason it is not on by default.

func SetPageSize

func SetPageSize(bytes uint32) *PragmaStatement

SetPageSize sets PRAGMA page_size, the size of every page in the database file.

Build refuses a size that is not a power of two from 512 to 65536, because SQLite does not: it accepts the statement, ignores the value and leaves the page size alone, measured on 3.50.3 with 1000, which is exactly the silent wrong answer this module exists to turn into an error.

Even a legal size only takes effect on a database with no pages yet, so this belongs before the first CREATE TABLE; on a database that already has content the size changes when a VACUUM rewrites the file, and the statement is marked OutsideTransaction so that a caller can run that VACUUM after it.

func SetSecureDelete

func SetSecureDelete(s SecureDelete) *PragmaStatement

SetSecureDelete sets PRAGMA secure_delete.

func SetSynchronous

func SetSynchronous(s Synchronous) *PragmaStatement

SetSynchronous sets PRAGMA synchronous, per connection.

The statement is marked OutsideTransaction: SQLite raises "Safety level may not be changed inside a transaction", measured on 3.50.3, so a runner that batched it with the rest of a migration would fail the migration for the ordering rather than for the schema.

func SetTempStore

func SetTempStore(s TempStore) *PragmaStatement

SetTempStore sets PRAGMA temp_store, per connection. TempStoreMemory trades memory for speed and will fail a query whose sort does not fit.

func SetUserVersion

func SetUserVersion(n int32) *PragmaStatement

SetUserVersion sets PRAGMA user_version, an integer in the database header that SQLite stores and never reads: a migration ledger with no table, for a database one library owns.

func (*PragmaStatement) Build

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

Build renders the statement.

type RaiseAction

type RaiseAction int

RaiseAction is what RAISE does to the statement that fired the trigger.

const (
	RaiseRollback RaiseAction = iota + 1
	RaiseAbort
	RaiseFail
)

The raise actions that carry a message. Rollback undoes the whole transaction; Abort undoes only the statement, which is SQLite's default for a constraint violation; Fail stops the statement where it is and keeps the changes it has already made, which is almost never what a validation wants.

type RawJSON

type RawJSON = json.RawMessage

RawJSON is json.RawMessage, re-exported so a caller declaring a JSON column does not need a second import to say what the column holds.

type RebuildQuery

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

RebuildQuery is a table rebuild with no new definition yet.

func Rebuild

func Rebuild(old sqlb.Table) *RebuildQuery

Rebuild starts the table rebuild SQLite's documentation gives for every change ALTER TABLE cannot make: a column's type, a constraint, a key. It creates the new table, copies the rows, drops the old one and renames the new one into its place, with foreign-key enforcement off for the duration.

func (*RebuildQuery) Into

Into gives the new table's definition. Its table must have another name, which the rebuild renames to the old one at the end.

type RebuildStatement

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

RebuildStatement is a rebuild with its new definition.

func (*RebuildStatement) Build

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

Build renders the rebuild. It holds no BEGIN or COMMIT: its first and last statements, which turn foreign-key enforcement off and on, are marked OutsideTransaction, and a runner executes everything between them in one transaction. The foreign-key check before the end is MustReturnNoRows.

func (*RebuildStatement) Copy

func (x *RebuildStatement) Copy(first CopyPair, more ...CopyPair) *RebuildStatement

Copy says how each column of the new table is filled from the old one.

func (*RebuildStatement) Recreate

func (x *RebuildStatement) Recreate(bs ...interface{ Build() (ddl.Script, error) }) *RebuildStatement

Recreate names the indexes, triggers and views on the old table, which the DROP removes and nothing brings back. The rebuild cannot find them without reading the database, which ADR-0003 keeps out, so the author lists them; a rebuild that forgets one silently loses it, which is why the execution test compares sqlite_schema before and after.

type RefAction

type RefAction int

RefAction is what a foreign key does when the row it references is deleted or updated. SQLite enforces foreign keys only with PRAGMA foreign_keys on, which contrib/driver-sqlite sets on every connection.

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

The referential actions.

type SecureDelete

type SecureDelete int

SecureDelete is what SQLite writes over a deleted row's bytes.

const (
	SecureDeleteOff SecureDelete = iota + 1
	SecureDeleteOn
	SecureDeleteFast
)

The secure-delete modes. Off leaves the content in the free page until something else overwrites it, so a deleted secret is still in the file. On zeroes it, at the cost of writing those pages. Fast zeroes only what it can do without extra page writes, which covers the common case of a row deleted from a page that is being rewritten anyway.

type SelectClause

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

SelectClause is a clause for a SELECT on this engine.

func IndexedBy

func IndexedBy(index string) SelectClause

IndexedBy forces a query to use one index on a table reference, and NotIndexed forbids every index on one.

INDEXED BY is per table reference, not per statement, so where you put the clause decides which table it binds to. On the driving table it goes in the statement, which renders it in SlotAfterFrom:

sel.From(t).Clause(sqlite.IndexedBy("idx_t_name"))

On a joined table it goes in that join, because a statement slot names one position per statement and a join needs one of its own:

sel.Join(sqlb.Join{Type: sqlb.JoinInner, Table: other, On: ...,
	Clauses: []sqlb.AnyClause{sqlite.IndexedBy("idx_other_id")}})

Putting the joined table's hint in the statement binds it to the driving table instead, which names an index that table does not have.

Both are for the case where the planner has chosen wrong and you can prove it. They are a maintenance hazard: dropping or renaming the named index turns every query carrying this clause into an error rather than a slower query, which is why SQLite documents them as a debugging aid rather than a tuning tool.

func NotIndexed

func NotIndexed() SelectClause

NotIndexed renders NOT INDEXED, forbidding every index on the source.

type SelectQuery

type SelectQuery = sqlb.Select[Dialect]

SelectQuery is the statement type Select returns. The aliases below carry a Query suffix because Go cannot give a type and a function one name in a package; an alias is the type itself, so a value passes through either name with no conversion.

func Select

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

Select starts a SELECT for SQLite. Items passed here are added without scan targets, for a subquery, a CTE body or a view; a query that will be scanned calls Select() with no items and adds bindings with Columns.

type Synchronous

type Synchronous int

Synchronous is how hard SQLite makes the filesystem promise a commit reached the disk.

const (
	SynchronousOff Synchronous = iota + 1
	SynchronousNormal
	SynchronousFull
	SynchronousExtra
)

The synchronous levels. Normal is the documented companion of WAL: a process crash cannot lose a commit, only a power loss can, and it costs a fraction of Full. Off means the database can be corrupted by a power loss, not merely missing its last commits.

type TableClause

type TableClause = ddl.TableClause[Dialect]

TableClause is a SQLite clause for CREATE TABLE.

func Strict

func Strict() TableClause

Strict makes SQLite enforce column types, which a library that scans into typed Go values wants: without it a TEXT column accepts an integer and the scan fails later, far from the write. It restricts column types to INT, INTEGER, REAL, TEXT, BLOB and ANY, which the type table's SQLite spellings already are.

func Temporary

func Temporary() TableClause

Temporary makes the table live in the temp schema and vanish when the connection closes.

It renders between CREATE and TABLE, which is the one position an engine clause can occupy there, and it checks the whole table rather than itself: SQLite refuses a temporary table whose name is qualified by any schema but temp, so a table declared with one fails Build with ErrTemporaryTable instead of reaching the server.

The pooling warning matters more here than the syntax. With database/sql a temporary table created by one statement is invisible to the next unless both ran on the same connection, and the pool decides that. Create it inside a transaction, or on a connection taken with Conn, and never assume a later query will find it.

func WithoutRowID

func WithoutRowID() TableClause

WithoutRowID stores the table as its primary key's index, which a table keyed by something other than an integer is smaller and faster as. It needs a primary key, and SQLite refuses the table without one.

type TableConstraint

type TableConstraint = ddl.TableConstraint

TableConstraint is a named constraint of one table, declared once. See ddl.TableConstraint.

type TempStore

type TempStore int

TempStore is where SQLite puts a temporary table or index, and the sort files a large ORDER BY or a VACUUM needs.

const (
	TempStoreDefault TempStore = iota + 1
	TempStoreFile
	TempStoreMemory
)

The temp stores. Default defers to how the library was compiled, which is the thing a caller setting this pragma is usually trying to stop depending on.

type TimedTriggerQuery

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

TimedTriggerQuery is CREATE TRIGGER with its timing and no body yet.

func (*TimedTriggerQuery) Do

Do gives the body, at least one statement, and so completes the trigger.

func (*TimedTriggerQuery) When

When fires the trigger only for rows matching p, written with Old and New.

type Tokenizer

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

Tokenizer is how an FTS5 table splits text into terms.

func ASCII

func ASCII() Tokenizer

ASCII folds only ASCII case, and is faster.

func Porter

func Porter(inner Tokenizer) Tokenizer

Porter stems English words over another tokenizer, so "running" matches "run".

func Trigram

func Trigram() Tokenizer

Trigram indexes every three-character sequence, which serves substring search and LIKE rather than word search.

func Unicode61

func Unicode61(removeDiacritics int) Tokenizer

Unicode61 is FTS5's default tokenizer, folding case for every script. removeDiacritics is 0, 1 or 2: 2 folds diacritics correctly for combining characters, which is what a search box wants.

type Trigger

type Trigger struct{ Name, Schema string }

Trigger is a SQLite trigger; its name is unique per database.

Schema names the database the trigger is created in, empty for main. The table the trigger fires on is written unqualified, because a non-temporary trigger must be in the same database as its table.

type TriggerEvent

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

TriggerEvent is the one event that fires a SQLite trigger; SQLite takes one per trigger, so there is no list.

func OnDelete

func OnDelete() TriggerEvent

OnDelete fires on DELETE.

func OnInsert

func OnInsert() TriggerEvent

OnInsert fires on INSERT.

func OnUpdate

func OnUpdate() TriggerEvent

OnUpdate fires on any UPDATE.

func OnUpdateOf

func OnUpdateOf(first ddl.ColumnRef, more ...ddl.ColumnRef) TriggerEvent

OnUpdateOf fires on an UPDATE whose SET names one of cols.

type TriggerStep

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

TriggerStep is one statement in a trigger's body. It is closed to the four constructors below, each typed to a complete SQLite statement, so the typestate that stops an unfiltered UPDATE compiling stops one inside a trigger too, and a Postgres statement does not fit.

func StepDelete

func StepDelete(s *FilteredDelete) TriggerStep

StepDelete is a DELETE in a trigger body.

func StepInsert

func StepInsert(s *InsertReady) TriggerStep

StepInsert is an INSERT in a trigger body.

func StepSelect

func StepSelect(s *SelectQuery) TriggerStep

StepSelect is a SELECT in a trigger body, which is how a trigger raises an error through a function such as RAISE.

func StepUpdate

func StepUpdate(s *FilteredUpdate) TriggerStep

StepUpdate is an UPDATE in a trigger body.

type Unit

type Unit string

Unit is the unit of a relative time offset. It is a closed set, unlike Modifier itself, because these six are the whole vocabulary.

const (
	Day    Unit = "days"
	Hour   Unit = "hours"
	Minute Unit = "minutes"
	Second Unit = "seconds"
	Month  Unit = "months"
	Year   Unit = "years"
)

The offset units. SQLite accepts the singular and the plural of each, measured; the plural is written because it reads correctly for every count including one.

type UpdateClause

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

UpdateClause is a clause for an UPDATE on this engine.

type UpdateQuery

type UpdateQuery = sqlb.Update[Dialect]

UpdateQuery is the statement Update returns. It has no Build until Where or All says which rows, so an unfiltered UPDATE does not compile.

func Update

func Update(t sqlb.Table) *UpdateQuery

Update starts an UPDATE of t for SQLite.

type View

type View struct{ Name, Schema string }

View is a SQLite view.

Schema names the database the view is created in, empty for main; a temporary view is Temporary rather than Schema "temp", though SQLite accepts both.

Jump to

Keyboard shortcuts

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