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, and, for a projection base, its key and field contract. 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. 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 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) GuardedRow[T any](check Rows[T], version string, current func(T) int64) RowGuard[T]
- 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) 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 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 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
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's check read, 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 RowGuard ¶ added in v0.2.0
type RowGuard[T any] struct { // contains filtered or unexported fields }
RowGuard is Guard's counterpart for a command with its own second predicate: check reads the whole row instead of a bare version, so Run can tell no row at all, a row at another version, and a row at the expected version the command's own predicate refused apart, where Guard could only ever report the last two cases as the same version mismatch.
func (RowGuard[T]) Run ¶ added in v0.2.0
func (g RowGuard[T]) Run(ctx context.Context, s sqlate.Session, version int64, args Args) (int64, error)
Run executes the command with version bound under the guard's parameter name alongside args, exactly as Guard.Run. A row affected is success and the new version, version+1, with no second round trip. No row affected reads the row with the check, using the same bound args: no row is sql.ErrNoRows; a row whose current version (read through the current function) 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 is what refused the write.
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) GuardedRow ¶ added in v0.2.0
func (st Statement) GuardedRow[T any](check Rows[T], version string, current func(T) int64) RowGuard[T]
GuardedRow binds the statement, a guarded command whose own predicate may refuse a row the key and version alone would have matched, to a row-returning check: version names the parameter both bind the expected version to, and current reads a checked row's own version.
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, or one 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) 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