Documentation
¶
Overview ¶
Package query runs authored SQL files: Statements compiled from an fs.FS against a Catalog give a program its statements by name, each file's "--|" header declaring its tier, the engine feature a native file uses, whether it needs a transaction, for a projection base its key and field contract, and, for an INSERT INTO or UPDATE, the read that returns its changed row. The catalog is the registered pattern sources (the library's own Patterns(), an application's, an engine's overlay), built once, where the program starts; a statement includes a pattern with {{> ns.name}}. Parameters, written {{name}} or {{name:type}} (the type binding through CAST, verbatim), resolve to the dialect's positions once at load; arguments bind from Args by name. The engine receives the body: the header is the loader's. The runners are generic over a consumer-written scan function and take a Session, so a handle runs against the pool or inside a transaction alike; every error is mapped through the dialect at the runner boundary. A returning command's handle, Statement.Returning, runs the command and returns the row as it stands afterward: in one statement when the dialect implements Returner, otherwise the command and then its read as one unit. Verify prepares every statement against the live schema. Statement text is build-time only: files under embed, never request input.
Index ¶
- Constants
- Variables
- func Scalar[T any](rows *sql.Rows) (T, error)
- func Verify(ctx context.Context, db sqlate.Session, vs ...Verifier) error
- type Args
- type ArgumentError
- type Catalog
- type Collection
- type Cursor
- type CursorError
- type CursorReason
- type Directives
- type Field
- type FieldUse
- type Filter
- type Guard
- type InvalidValueError
- type Op
- type Page
- type Pattern
- type Projection
- func (p Projection[T]) Continue(ctx context.Context, s sqlate.Session, d Directives, after Cursor, size int, ...) (Collection[T], error)
- func (p Projection[T]) List(ctx context.Context, s sqlate.Session, d Directives, page Page, base ...Args) (Collection[T], error)
- func (p Projection[T]) One(ctx context.Context, s sqlate.Session, field string, value any, base ...Args) (T, error)
- func (p Projection[T]) Statement() Statement
- func (p Projection[T]) Verify(ctx context.Context, db sqlate.Session) error
- type RefusedError
- type Returner
- type Returning
- type RowGuard
- type Rows
- type ScanFunc
- type Sort
- type Source
- type Statement
- func (st Statement) Catalog() *Catalog
- func (st Statement) Exec(ctx context.Context, s sqlate.Session, args Args) (int64, error)
- func (st Statement) Fields() []Field
- func (st Statement) Guarded(check Statement, version string) Guard
- func (st Statement) Key() string
- func (st Statement) Keys() []string
- func (st Statement) Name() string
- func (st Statement) Native() string
- func (st Statement) Params() []string
- func (st Statement) Port() string
- func (st Statement) Project[T any](scan ScanFunc[T]) Projection[T]
- func (st Statement) Reads() string
- func (st Statement) Returning[T any](scan ScanFunc[T]) Returning[T]
- func (st Statement) ReturningText() string
- func (st Statement) Scan[T any](scan ScanFunc[T]) Rows[T]
- func (st Statement) Text() string
- func (st Statement) Tier() Tier
- func (st Statement) TransactionRequired() bool
- type Statements
- type Tier
- type TotalMode
- type UnknownFieldError
- type UnknownOperatorError
- type Verb
- type Verifier
Constants ¶
const Namespace = "sql"
Namespace is the library's own namespace: every include is qualified, as {{> sql.guard_where}}, so a pattern's origin is visible in the statement and two sources cannot collide. It is reserved: the library always registers under it, and no other source may claim it. Another registrant aliases its own namespace with As, the way an import is aliased, as the last resort against a collision.
const NoTotal = -1
NoTotal is Collection.Total when the request declined the count.
Variables ¶
var ErrDirectives = errors.New("query: invalid declarations")
ErrDirectives is the request sentinel: every error a read request's declarations can cause unwraps to it, so a consumer's matcher is one errors.Is for 400.
var ErrNotOneRow = errors.New("query: a returning command did not yield exactly one row")
ErrNotOneRow reports a returning command that changed more than one row, or whose read found no row after the command changed one. Either is a defect in the declaration, not request input: the command's WHERE is not a key, or the read does not find the row the command changed.
var ErrRefused = errors.New("refused")
ErrRefused classifies a guarded command whose row exists, at the version the caller expected, but whose own predicate — beyond the key and the version — still matched no row. A plain Guard's command carries no such predicate, so its own equal-version branch can never actually be reached: a row at the expected version would already have matched the command's update. RowGuard's second predicate is what makes this a real, reachable outcome.
var ErrTransactionRequired = errors.New("query: statement requires a transaction")
ErrTransactionRequired reports a statement headed "-- transaction: required" run on a session that is not a transaction: the one silent hazard, a transaction-scoped lock outside one, made loud.
var ErrVersionMismatch = errors.New("version mismatch")
ErrVersionMismatch classifies a guarded command whose row exists at another version than the one the caller read: the optimistic-concurrency protocol's own conflict, with the expected and current versions in its text. A service maps it to 412.
Functions ¶
Types ¶
type Args ¶
Args binds a statement's named parameters. A missing name is an ArgumentError; an extra name is ignored, so one map serves a guard's command and its narrower check.
func ArgsOf ¶
ArgsOf binds a struct's fields as Args by their column names; a nil pointer binds NULL. It is the command-side twin of Scanner.
type ArgumentError ¶
type ArgumentError struct {
Statement string
Name string
// Problem says what was wrong with an argument that was present; empty
// means it was missing.
Problem string
}
ArgumentError reports a parameter the Args did not include. It is a programming error in the caller, not request input, and matches no request sentinel.
func (*ArgumentError) Error ¶
func (e *ArgumentError) Error() string
type Catalog ¶
type Catalog struct {
// contains filtered or unexported fields
}
Catalog is the registered pattern sources, read and validated once, and the context every statement compiles against. It is read-only after NewCatalog and safe for concurrent use.
func MustCatalog ¶
MustCatalog is NewCatalog for the place a program starts, where a catalog error is a defect.
func NewCatalog ¶
NewCatalog reads every source and validates it:
- each file declares a tier
- a native file names its port
- a pattern includes no other pattern
- an overlay respells only what its source defines, with the same slots or the pattern's alternate set
- no two sources share a namespace
- only the library's source registers under Namespace, and it registers under no other
Every failure is reported, joined, each naming the namespace and file.
func (*Catalog) Compile ¶
Compile reads every .sql file under dir in fsys, parses its header, expands its includes against the catalog, and resolves its parameters against d's placeholders. A load error names the file and is a defect in the program's own files, not a runtime condition. It's a load error when a file:
- has no header
- has an unknown declaration
- has a header the grammar rejects
- has an include the catalog cannot resolve
- declares returning and is not a standard-tier INSERT INTO or UPDATE, or also declares a key or field
- declares returning and names a read that is missing, declares returning, a key, a field, or a required transaction, takes a parameter the command does not, or is not SELECT <column>, … FROM … with every column under one qualifier or none, each named once
- declares returning, and the dialect's single-statement form of it introduces a {{
func (*Catalog) MustCompile ¶
MustCompile is Compile for the place a program binds its statements, where a load error is a defect.
func (*Catalog) Namespaces ¶
Namespaces returns the registered namespaces in name order.
type Collection ¶ added in v0.2.0
Collection is one page of a collection read: the items, the total under the request's filters (NoTotal when the request declined the count), whether a further page exists, and the cursor that continues from this page's last item, empty when More is false or the ordering cannot be continued by cursor.
type Cursor ¶ added in v0.2.0
type Cursor string
Cursor is an opaque position in a collection read's ordering: the keyed values of the last item of a page and a fingerprint of the filters that produced it, issued as Collection.Next and accepted back by Continue under the same filters. It is URL-safe text a consumer relays verbatim; its content is not a contract and a consumer never builds one.
type CursorError ¶ added in v0.2.0
type CursorError struct {
Reason CursorReason
}
CursorError reports a cursor Continue cannot continue from.
func (*CursorError) Error ¶ added in v0.2.0
func (e *CursorError) Error() string
func (*CursorError) Unwrap ¶ added in v0.2.0
func (e *CursorError) Unwrap() error
type CursorReason ¶ added in v0.2.0
type CursorReason string
CursorReason classifies a rejected cursor.
const ( // CursorMalformed is a cursor List did not issue: it does not decode, or // does not verify against the projection's keyed fields and their types. CursorMalformed CursorReason = "malformed" // CursorMismatch is a cursor issued for another base, another ordering, // or under other filters. CursorMismatch CursorReason = "mismatch" // CursorUnsupported is a request whose sort cannot continue from a // cursor: the keyed prefix mixes directions or includes a nullable field. CursorUnsupported CursorReason = "unsupported" )
type Directives ¶
type Directives struct {
Sort []Sort
Filters []Filter
// Total says whether the read counts; the zero value does.
Total TotalMode
}
Directives is one read request against a projection. Filters and Sort reference contract field names; an unknown name is an UnknownFieldError, never SQL.
type Field ¶
Field is one entry of a projection base's field contract: the name a request may filter or sort by, and the SQL type a request value is cast to when it does, written as the engine reads it. NotNull reports the declaration's trailing "not null"; a field declared without it is presumed nullable.
type FieldUse ¶
type FieldUse string
FieldUse names the declaration position where a contract field was referenced; UnknownFieldError records it.
type Filter ¶
Filter is one filter declaration: a contract field, an operator, and the value. OpIsNull and OpIsNotNull ignore Value; OpIn requires a []any. A value binds as given, a request's text included, cast to the field's declared type, so the engine parses it and a value it cannot read is an InvalidValueError.
type Guard ¶
type Guard struct {
// contains filtered or unexported fields
}
Guard is the optimistic-concurrency protocol over two authored statements: the command, whose WHERE names the key and the expected version and whose SET advances it, and the check, which reads the row's current version by key. The SQL is the consumer's; the guard is the function over it.
func (Guard) Run ¶
Run executes the command with version bound under the guard's parameter name alongside args. A row affected is success and the new version, version+1, with no second round trip. No row affected runs the check with the same args: no row is sql.ErrNoRows, a row is ErrVersionMismatch with the expected and current versions.
type InvalidValueError ¶
InvalidValueError reports a filter value the projection or the engine could not use: a value of the wrong shape for its operator, named by field, or a bound value the engine rejected for the field's type, in which case Field is empty and Err is the engine's error.
func (*InvalidValueError) Error ¶
func (e *InvalidValueError) Error() string
func (*InvalidValueError) Unwrap ¶
func (e *InvalidValueError) Unwrap() []error
type Op ¶
type Op string
Op is a filter declaration's operator. The values are short strings so a read contract can state them verbatim.
type Page ¶
Page is the 1-based page declaration of a read: which page, and how many rows per page. Both must be at least 1.
type Pattern ¶
type Pattern struct {
Namespace string
Name string
Tier Tier
Native string
Slots []string
Alternate []string
Text string
}
Pattern is one catalog entry as the inventory reports it: its namespace, name, tier, native note, slots in body order, the alternate slots an overlay may declare instead, and body.
type Projection ¶
type Projection[T any] struct { // contains filtered or unexported fields }
Projection is a base statement bound to a scan function and its declared field contract: the typed handle for a collection read. The collection pattern wraps the base as a derived table, so the base may be any query, a recursive CTE or a join tree, and the only names a declaration can reference are the base's output columns the header declared. The base's own parameters bind from the base arguments List, Continue, and One take, merged left to right with a later value winning.
Every part of the composed text is a pattern of the library's namespace in the base's catalog, as the library published it or an engine overlaid it; this code does only what cannot be text: the whitelist check against the header, list arity, and parameter positions.
func (Projection[T]) Continue ¶ added in v0.2.0
func (p Projection[T]) Continue(ctx context.Context, s sqlate.Session, d Directives, after Cursor, size int, base ...Args) (Collection[T], error)
Continue runs the collection read from where a previous List or Continue left off: the size rows past after's position, under the same sort that issued it. after must be a Collection.Next a previous read returned; List reads a request's first page. The total and the next cursor are as List reports them.
func (Projection[T]) List ¶
func (p Projection[T]) List(ctx context.Context, s sqlate.Session, d Directives, page Page, base ...Args) (Collection[T], error)
List runs the collection read by offset: the page under the declarations, the total under the same filters unless the request declined it, and the cursor that continues past the page. Sorts gain the key fields they do not already name, so the ordering is total and paging is stable; a page reads one row past its size to report whether a further page exists.
func (Projection[T]) One ¶
func (p Projection[T]) One(ctx context.Context, s sqlate.Session, field string, value any, base ...Args) (T, error)
One runs the single-row read: the base under one equality filter on a contract field. No row is sql.ErrNoRows; when the field is not unique the first row wins.
func (Projection[T]) Statement ¶
func (p Projection[T]) Statement() Statement
Statement returns the base.
func (Projection[T]) Verify ¶
Verify prepares two probes over the base. The first names every contract field and compares it against a cast of its declared type, so a field the base no longer outputs, or one whose type no longer matches, fails at startup. The second is one page past a cursor over the key alone, so the keyset predicate and the paging clause, an engine's own respelling of either included, are prepared at startup too.
type RefusedError ¶ added in v0.2.0
RefusedError is a guarded command's row-level refusal: the row RowGuard read back, at the version the caller expected. Unwrap yields ErrRefused.
func (*RefusedError[T]) Error ¶ added in v0.2.0
func (e *RefusedError[T]) Error() string
func (*RefusedError[T]) Unwrap ¶ added in v0.2.0
func (e *RefusedError[T]) Unwrap() error
type Returner ¶ added in v0.3.0
type Returner interface {
Returning(verb Verb, body string, columns []string) (text string, ok bool)
}
Returner is the dialect capability that renders a returning command's single-statement form, the command that returns its changed row. body is the command after include expansion, its parameters still {{…}} slots; columns are the read's bare column names in scan order. Returning with ok=false declines, and the command runs the fallback: the command and then its read. An implementation declines a Verb it does not know.
type Returning ¶ added in v0.3.0
type Returning[T any] struct { // contains filtered or unexported fields }
Returning is a returning command bound to the scan of its read: the handle that runs the command and returns the row as it stands afterward. It is a value, built once in a constructor and held.
func (Returning[T]) Guarded ¶ added in v0.3.0
Guarded binds the handle, a command whose WHERE names the key and the expected version, to the optimistic-concurrency protocol: version names the command's parameter the expected version binds to, and current reads a row's own version. A version that is not a parameter of the command is a defect in the caller's constructor and panics.
func (Returning[T]) One ¶ added in v0.3.0
One runs the command and returns the row as it stands afterward, and whether the command changed it. When the command changed no row, One reads the row as it is and returns changed=false; no row at all is sql.ErrNoRows, unmapped. A command that changed more than one row, or whose read finds no row after the command changed one, is ErrNotOneRow. A command headed "transaction: required" is ErrTransactionRequired outside a *sqlate.Tx, on either form, before any SQL runs.
The single-statement form is one query on s, atomic by itself. When it returns a second row, that row has already changed, and only the caller's transaction can undo the change. The fallback runs the command and then its read as one unit: inside s when s is a *sqlate.Tx; inside a transaction One opens, commits, and rolls back on any error when s is a sqlate.Beginner, as sqlate.Transact runs a unit; and on any other session One returns ErrTransactionRequired.
The two forms return the same row for a sound declaration: a read that selects exactly the row the command changed, from the command's own table, which the load checks as far as the table. They differ when the command changes more than one row outside a transaction (the single-statement form's change has committed before ErrNotOneRow; the fallback's own transaction rolls back), when the read does not find the changed row (the single-statement form returns the RETURNING row; the fallback returns ErrNotOneRow), and on a session that is neither a *sqlate.Tx nor a sqlate.Beginner, where only the single-statement form runs.
type RowGuard ¶ added in v0.2.0
type RowGuard[T any] struct { // contains filtered or unexported fields }
RowGuard is Guard's counterpart over a returning command whose own predicate, beyond the key and the version, may refuse the write. It returns the row as it stands afterward. When the command changed nothing, it uses the row the returning handle already read back to tell apart no row at all, a row at another version, and a row at the expected version that the command's own predicate refused. Returning.Guarded builds it.
func (RowGuard[T]) Run ¶ added in v0.2.0
func (g RowGuard[T]) Run(ctx context.Context, s sqlate.Session, version int64, args Args) (T, error)
Run runs the command through its handle's One, with version bound under the guard's parameter name alongside args. A changed row is success: Run returns the row as it stands afterward, whose new version is current(row). An unchanged row is classified: no row is sql.ErrNoRows; a row whose current version does not match the expected one is ErrVersionMismatch, with both versions in its text; a row at the expected version is a *RefusedError[T] carrying it, since the command's own predicate refused the write. Every error One returns, ErrNotOneRow among them, passes through.
type Rows ¶
type Rows[T any] struct { // contains filtered or unexported fields }
Rows is a statement bound to a scan function: the typed handle a program keeps for a query that returns rows.
func (Rows[T]) Each ¶
Each yields the rows one at a time; the row set closes when the loop ends, by exhaustion or by break. A failure is the final pair's error.
type ScanFunc ¶
ScanFunc reads the current row into a T. The consumer writes one per row shape; the SELECT list is the scan order.
type Source ¶
type Source struct {
// contains filtered or unexported fields
}
Source is one namespace's patterns, declared as a directory and any overlays, read and validated when a Catalog is built. It is a value: As and Overlay return a new source and leave the receiver as it was.
func Patterns ¶
func Patterns() Source
Patterns is the library's own patterns under Namespace: the collection read's request-time patterns and the protocol patterns a statement includes. A catalog that serves a Projection includes it, and it always registers under Namespace.
func Publish ¶
Publish declares the .sql files under dir in fsys as the patterns of namespace: a pattern source. Nothing is read until NewCatalog.
func (Source) As ¶
As registers the source under another namespace, so an include reads {{> ns.name}} for it; the last resort when two sources would collide. The library's own source is the exception: NewCatalog refuses it under any namespace but Namespace.
func (Source) Overlay ¶
Overlay replaces patterns of the source by name with the files under dir in fsys: an engine supplies its own paging. The replacement is explicit (a file that names no pattern of the source, or declares neither the pattern's own slots nor its alternate set, is a catalog error), so an overlay can only respell what the source already defines. A later overlay wins over an earlier one.
type Statement ¶
type Statement struct {
// contains filtered or unexported fields
}
Statement is one authored file, compiled: its text with the dialect's placeholders and its includes spliced, its parameters in position order, and its header. It references the catalog it compiled against and its dialect, so a projection over it composes from the same patterns. It is a value, fetched by name once in a constructor and held in a typed handle.
func (Statement) Guarded ¶
Guarded binds the statement, a guarded command, to its version check; version names the parameter both bind the expected version to.
func (Statement) Key ¶
Key is the declared key of a projection base, as the header declares it: a composite key's parts in header order, joined by ", ". It is empty when none is declared.
func (Statement) Keys ¶ added in v0.2.0
Keys is the declared key of a projection base, its parts in header order; empty when none is declared.
func (Statement) Native ¶
Native is the native declaration: the engine feature used and the port, for a native statement; empty for a standard one.
func (Statement) Port ¶ added in v0.2.0
Port is the port declaration: how the statement is ported to another engine, for a native statement; empty when none is declared.
func (Statement) Project ¶
func (st Statement) Project[T any](scan ScanFunc[T]) Projection[T]
Project binds the statement, a projection base, to scan: the typed handle for the collection read. A base without a key or field contract, a returning command, or a base that takes an expanded parameter is a defect in the caller's constructor and panics. A base's own non-expanded parameters bind from the base arguments List, Continue, and One take.
func (Statement) Reads ¶ added in v0.3.0
Reads is the name of the read the statement's returning declaration names: the statement that reads the changed row back. It is empty when none is declared.
func (Statement) Returning ¶ added in v0.3.0
Returning binds the statement, a returning command, to scan, the scan function of the read its returning declaration names; the read's SELECT list is the scan order on both forms. A statement that declares no returning is a defect in the caller's constructor and panics.
func (Statement) ReturningText ¶ added in v0.3.0
ReturningText is the single-statement form of a returning command as the engine receives it: the dialect's text, parameters rewritten to its placeholders, and for an expanded parameter the rendering at one element per list, the text Verify prepares. It is empty when no returning is declared or the dialect declined; the command then runs the fallback, the command and then its read.
func (Statement) Scan ¶
Scan binds the statement to scan: the typed handle for a query that returns rows.
func (Statement) Text ¶
Text is the SQL as the engine receives it: the file's body, parameters rewritten to the dialect's placeholders; the header is not sent. For a statement with an expanded parameter it is the rendering at one element per list, the text Verify prepares.
func (Statement) TransactionRequired ¶
TransactionRequired reports the "-- transaction: required" header.
type Statements ¶
type Statements struct {
// contains filtered or unexported fields
}
Statements is a set of related statements compiled from one directory: the inventory the verification step and an administrative listing walk, keyed by file name. It is not a registry; a program fetches each statement once, where it binds them.
func (*Statements) Statement ¶
func (s *Statements) Statement(name string) Statement
Statement returns the statement named by its file's base name; a missing name is a defect in the caller's constructor and panics.
func (*Statements) Statements ¶
func (s *Statements) Statements() []Statement
Statements returns the inventory in name order.
type TotalMode ¶ added in v0.2.0
type TotalMode int
TotalMode says whether a collection read counts the rows under its filters. The zero value counts.
type UnknownFieldError ¶
UnknownFieldError reports a sort or filter naming a field the projection does not declare. It is the field contract's boundary: the name is never written into the SQL.
func (*UnknownFieldError) Error ¶
func (e *UnknownFieldError) Error() string
func (*UnknownFieldError) Unwrap ¶
func (e *UnknownFieldError) Unwrap() error
type UnknownOperatorError ¶
type UnknownOperatorError struct {
Op Op
}
UnknownOperatorError reports a filter whose operator the vocabulary does not define.
func (*UnknownOperatorError) Error ¶
func (e *UnknownOperatorError) Error() string
func (*UnknownOperatorError) Unwrap ¶
func (e *UnknownOperatorError) Unwrap() error