query

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

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

View Source
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. A registrant aliases it with As, the way an import is aliased, as the last resort against a collision.

Variables

View Source
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.

View Source
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.

View Source
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

func Scalar

func Scalar[T any](rows *sql.Rows) (T, error)

Scalar is the ScanFunc for a single-column row.

func Verify

func Verify(ctx context.Context, db sqlate.Session, vs ...Verifier) error

Verify runs every verifier and joins their failures; startup and an administrative check call it with the same arguments.

Types

type Args

type Args map[string]any

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

func ArgsOf(v any) Args

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.

func (Args) With

func (a Args) With(name string, v any) Args

With returns a copy of a with name bound to v, for the inputs that arrive outside a command's body: the path id, the If-Match version.

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

func MustCatalog(sources ...Source) *Catalog

MustCatalog is NewCatalog for the place a program starts, where a catalog error is a defect.

func NewCatalog

func NewCatalog(sources ...Source) (*Catalog, error)

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, and no two sources share a namespace. Every failure is reported, joined, each naming the namespace and file.

func (*Catalog) Compile

func (c *Catalog) Compile(fsys fs.FS, dir string, d sqlate.Dialect) (*Statements, error)

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 file without a header, with an unknown declaration, with a header the grammar rejects, or with an include the catalog cannot resolve is a load error naming the file; a program treats it as a defect in its own files.

func (*Catalog) MustCompile

func (c *Catalog) MustCompile(fsys fs.FS, dir string, d sqlate.Dialect) *Statements

MustCompile is Compile for the place a program binds its statements, where a load error is a defect.

func (*Catalog) Namespaces

func (c *Catalog) Namespaces() []string

Namespaces returns the registered namespaces in name order.

func (*Catalog) Patterns

func (c *Catalog) Patterns() []Pattern

Patterns returns the inventory in namespace, then name, order.

type Directives

type Directives struct {
	Page    Page
	Sort    []Sort
	Filters []Filter
}

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

type Field struct {
	Name string
	Type string
}

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.

type FieldUse

type FieldUse string

FieldUse names the declaration position where a contract field was referenced; UnknownFieldError records it.

const (
	FieldUseSort   FieldUse = "sort"
	FieldUseFilter FieldUse = "filter"
)

type Filter

type Filter struct {
	Field string
	Op    Op
	Value any
}

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

func (g Guard) 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. 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

type InvalidValueError struct {
	Field string
	Err   error
}

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.

const (
	OpEq        Op = "eq"
	OpNe        Op = "ne"
	OpGt        Op = "gt"
	OpGe        Op = "ge"
	OpLt        Op = "lt"
	OpLe        Op = "le"
	OpLike      Op = "like"
	OpIsNull    Op = "null"
	OpIsNotNull Op = "notnull"
	OpIn        Op = "in"
)

type Page

type Page struct {
	Number int
	Size   int
}

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
	Text      string
}

Pattern is one catalog entry as the inventory reports it: its namespace, name, tier, native note, slots in body order, 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.

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]) List

func (p Projection[T]) List(ctx context.Context, s sqlate.Session, d Directives) ([]T, int, error)

List runs the collection read: the page under the declarations, and the total under the same filters. Sorts gain the key as the tie-breaker whenever the caller did not sort by it, so offset paging is stable.

func (Projection[T]) One

func (p Projection[T]) One(ctx context.Context, s sqlate.Session, field string, value any) (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

func (p Projection[T]) Verify(ctx context.Context, db sqlate.Session) error

Verify prepares a probe naming every contract field and the key over the base, so a field the base no longer outputs fails at startup.

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]) All

func (r Rows[T]) All(ctx context.Context, s sqlate.Session, args Args) ([]T, error)

All returns every row.

func (Rows[T]) Each

func (r Rows[T]) Each(ctx context.Context, s sqlate.Session, args Args) iter.Seq2[T, error]

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.

func (Rows[T]) One

func (r Rows[T]) One(ctx context.Context, s sqlate.Session, args Args) (T, error)

One returns the first row; no row is sql.ErrNoRows, unmapped.

func (Rows[T]) Statement

func (r Rows[T]) Statement() Statement

Statement returns the underlying statement.

type ScanFunc

type ScanFunc[T any] func(*sql.Rows) (T, error)

ScanFunc reads the current row into a T. The consumer writes one per row shape; the SELECT list is the scan order.

func Scanner

func Scanner[T any]() ScanFunc[T]

Scanner returns the ScanFunc for T from its tags: each row's columns are matched to fields by name, in the row's order, and scanned into a fresh T. A column T has no field for is an error, so a SELECT list that grows past its entity fails loudly; a field with no column stays zero.

type Sort

type Sort struct {
	Field      string
	Descending bool
}

Sort is one sort declaration, naming a contract field.

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, under Namespace or an alias.

func Publish

func Publish(namespace string, fsys fs.FS, dir string) Source

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

func (s Source) As(namespace string) Source

As registers the source under another namespace, so an include reads {{> ns.name}} for it; the last resort when two sources would collide.

func (Source) Namespace

func (s Source) Namespace() string

Namespace is the namespace the source registers under.

func (Source) Overlay

func (s Source) Overlay(fsys fs.FS, dir string) Source

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 different slots, 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) Catalog

func (st Statement) Catalog() *Catalog

Catalog is the catalog the statement compiled against.

func (Statement) Exec

func (st Statement) Exec(ctx context.Context, s sqlate.Session, args Args) (int64, error)

Exec runs the statement and returns the rows affected.

func (Statement) Fields

func (st Statement) Fields() []Field

Fields returns the declared field contract, in header order.

func (Statement) Guarded

func (st Statement) Guarded(check Statement, version string) Guard

Guarded binds the statement, a guarded command, to its version check; version names the parameter both bind the expected version to.

func (Statement) Key

func (st Statement) Key() string

Key is the declared key of a projection base; empty otherwise.

func (Statement) Name

func (st Statement) Name() string

Name is the file's base name without the .sql extension.

func (Statement) Native

func (st Statement) Native() string

Native is the native declaration: the engine feature used and the port, for a native statement; empty for a standard one.

func (Statement) Params

func (st Statement) Params() []string

Params returns the parameter names in position order.

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 binds parameters of its own, is a defect in the caller's constructor and panics.

func (Statement) Scan

func (st Statement) Scan[T any](scan ScanFunc[T]) Rows[T]

Scan binds the statement to scan: the typed handle for a query that returns rows.

func (Statement) Text

func (st Statement) Text() string

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

func (st Statement) Tier() Tier

Tier is the declared tier.

func (Statement) TransactionRequired

func (st Statement) TransactionRequired() bool

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.

func (*Statements) Verify

func (s *Statements) Verify(ctx context.Context, db sqlate.Session) error

Verify prepares every statement against db, so a reference the schema no longer satisfies fails here rather than at first request. Every failure is reported, joined, each naming its statement.

type Tier

type Tier string

Tier is a statement's declared portability.

const (
	// TierStandard is standard SQL: it runs on every engine the standard
	// covers with no port.
	TierStandard Tier = "standard"
	// TierNative uses one engine's own feature; the native declaration names
	// the feature and the port.
	TierNative Tier = "native"
)

type UnknownFieldError

type UnknownFieldError struct {
	Field string
	Use   FieldUse
}

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

type Verifier

type Verifier interface {
	Verify(ctx context.Context, db sqlate.Session) error
}

Verifier is what Verify composes: Statements, a Projection, anything that can check itself against the live schema.

Jump to

Keyboard shortcuts

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