Documentation
¶
Overview ¶
Package query builds SQL: the Builder, the raw Expression, the index hint and the join clause.
Builder is split across files by what each half does: builder.go holds the state and the clauses everything else builds on, wheres.go and havings.go the two filter vocabularies, joins.go and subqueries.go the join and subquery families, aggregates.go the counting and the pagination, chunk.go the walks, write.go the statements that change rows, execute.go the ones that read them, and misc.go the rest.
Nothing here decides who may run what ¶
A Builder compiles SQL. The tenant of the security.Grant is put on the statement at execution, in scoped, and on every subquery the statement carries -- a union, a `where exists`, a from, a join or a select subquery. That is not optional: a subquery is compiled whole, so a filter on the outer query says which of its rows survive and nothing about which rows went in.
A lateral join is JoinClause.Lateral rather than a type of its own, so the grammar has one type to hold. Dumping a query is Builder.Dump and Builder.DumpRawSQL, and neither ends the process.
Index ¶
- Constants
- Variables
- func IsExpression(value any) bool
- type AffectingConnection
- type Aggregate
- type BaseGrammar
- func (g *BaseGrammar) Columnize(columns []any) string
- func (g *BaseGrammar) CompileRandom(seed string) string
- func (g *BaseGrammar) CompileSavepoint(name string) string
- func (g *BaseGrammar) CompileSavepointRollBack(name string) string
- func (g *BaseGrammar) Escape(value any, binary bool) (string, error)
- func (g *BaseGrammar) GetBitwiseOperators() []string
- func (g *BaseGrammar) GetDateFormat() string
- func (g *BaseGrammar) GetOperators() []string
- func (g *BaseGrammar) GetTablePrefix() string
- func (g *BaseGrammar) Parameter(value any) string
- func (g *BaseGrammar) Parameterize(values []any) string
- func (g *BaseGrammar) QuoteString(value any) string
- func (g *BaseGrammar) SetTablePrefix(prefix string) Grammar
- func (g *BaseGrammar) SupportsSavepoints() bool
- func (g *BaseGrammar) Wrap(value any) string
- func (g *BaseGrammar) WrapArray(values []any) []string
- func (g *BaseGrammar) WrapTable(table any) string
- type Builder
- func (b *Builder) AddBinding(value []any, typ string) *Builder
- func (b *Builder) AddNestedHavingQuery(query *Builder, boolean string) *Builder
- func (b *Builder) AddNestedWhereQuery(query *Builder, boolean string) *Builder
- func (b *Builder) AddSelect(columns ...any) *Builder
- func (b *Builder) AddWhereExistsQuery(query *Builder, boolean string, not bool) *Builder
- func (b *Builder) AfterQuery(callback func([]Record) []Record) *Builder
- func (b *Builder) Aggregate(ctx context.Context, g auth.Grant, function string, columns ...any) (any, error)
- func (b *Builder) ApplyAfterQueryCallbacks(result []Record) []Record
- func (b *Builder) ApplyBeforeQueryCallbacks()
- func (b *Builder) Average(ctx context.Context, g auth.Grant, column any) (any, error)
- func (b *Builder) Avg(ctx context.Context, g auth.Grant, column any) (any, error)
- func (b *Builder) BeforeQuery(callback func(*Builder)) *Builder
- func (b *Builder) CastBinding(value any) any
- func (b *Builder) Chunk(ctx context.Context, g auth.Grant, count int, ...) (bool, error)
- func (b *Builder) ChunkById(ctx context.Context, g auth.Grant, count int, ...) (bool, error)
- func (b *Builder) ChunkByIdDesc(ctx context.Context, g auth.Grant, count int, ...) (bool, error)
- func (b *Builder) ChunkMap(ctx context.Context, g auth.Grant, callback func(row Record) any, count int) ([]any, error)
- func (b *Builder) CleanBindings(bindings []any) []any
- func (b *Builder) Clone() *Builder
- func (b *Builder) CloneWithout(properties ...string) *Builder
- func (b *Builder) CloneWithoutBindings(except ...string) *Builder
- func (b *Builder) Count(ctx context.Context, g auth.Grant, columns ...any) (int, error)
- func (b *Builder) CrossJoin(table any, first ...any) *Builder
- func (b *Builder) CrossJoinSub(query any, as string) *Builder
- func (b *Builder) Cursor(ctx context.Context, g auth.Grant) iter.Seq2[Record, error]
- func (b *Builder) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, ...) (*pagination.CursorPaginator[Record], error)
- func (b *Builder) Decrement(ctx context.Context, g auth.Grant, column string, amount float64, ...) (int64, error)
- func (b *Builder) DecrementEach(ctx context.Context, g auth.Grant, columns map[string]float64, ...) (int64, error)
- func (b *Builder) Delete(ctx context.Context, g auth.Grant, id ...any) (int64, error)
- func (b *Builder) Distinct(columns ...any) *Builder
- func (b *Builder) DoesntExist(ctx context.Context, g auth.Grant) (bool, error)
- func (b *Builder) DoesntExistOr(ctx context.Context, g auth.Grant, callback func() error) (bool, error)
- func (b *Builder) Dump(w io.Writer, args ...any) *Builder
- func (b *Builder) DumpRawSQL(ctx context.Context, g auth.Grant, w io.Writer) *Builder
- func (b *Builder) DynamicWhere(method string, parameters []any) *Builder
- func (b *Builder) Each(ctx context.Context, g auth.Grant, callback func(row Record, index int) bool, ...) (bool, error)
- func (b *Builder) EachById(ctx context.Context, g auth.Grant, callback func(row Record, index int) bool, ...) (bool, error)
- func (b *Builder) Err() error
- func (b *Builder) Exists(ctx context.Context, g auth.Grant) (bool, error)
- func (b *Builder) ExistsOr(ctx context.Context, g auth.Grant, callback func() error) (bool, error)
- func (b *Builder) Find(ctx context.Context, g auth.Grant, id any, columns ...any) (Record, error)
- func (b *Builder) FindOr(ctx context.Context, g auth.Grant, id any, columns []any, ...) (Record, error)
- func (b *Builder) First(ctx context.Context, g auth.Grant, columns ...any) (Record, error)
- func (b *Builder) FirstOr(ctx context.Context, g auth.Grant, columns []any, ...) (Record, error)
- func (b *Builder) FirstOrFail(ctx context.Context, g auth.Grant, columns []any, message ...string) (Record, error)
- func (b *Builder) ForNestedWhere() *Builder
- func (b *Builder) ForPage(page, perPage int) *Builder
- func (b *Builder) ForPageAfterId(perPage int, lastId any, column string) *Builder
- func (b *Builder) ForPageBeforeId(perPage int, lastId any, column string) *Builder
- func (b *Builder) ForceIndex(index string) *Builder
- func (b *Builder) From(table any, as ...string) *Builder
- func (b *Builder) FromRaw(expression string, bindings ...any) *Builder
- func (b *Builder) FromSub(query any, as string) *Builder
- func (b *Builder) Get(ctx context.Context, g auth.Grant, columns ...any) ([]Record, error)
- func (b *Builder) GetAggregate() *Aggregate
- func (b *Builder) GetBindings() []any
- func (b *Builder) GetColumns() []any
- func (b *Builder) GetConnection() Connection
- func (b *Builder) GetCountForPagination(ctx context.Context, g auth.Grant, columns ...any) (int, error)
- func (b *Builder) GetDistinct() any
- func (b *Builder) GetFrom() any
- func (b *Builder) GetGrammar() Grammar
- func (b *Builder) GetGroupLimit() *GroupLimit
- func (b *Builder) GetIndexHint() *IndexHint
- func (b *Builder) GetLimit() *int
- func (b *Builder) GetLock() any
- func (b *Builder) GetOffset() *int
- func (b *Builder) GetProcessor() Processor
- func (b *Builder) GetRawBindings() map[string][]any
- func (b *Builder) GetTimeout() *int
- func (b *Builder) GroupBy(groups ...any) *Builder
- func (b *Builder) GroupByRaw(sql string, bindings ...any) *Builder
- func (b *Builder) GroupLimit(value int, column string) *Builder
- func (b *Builder) Having(column any, args ...any) *Builder
- func (b *Builder) HavingBetween(column any, values []any, boolean string, not bool) *Builder
- func (b *Builder) HavingNested(callback func(*Builder), boolean string) *Builder
- func (b *Builder) HavingNotBetween(column any, values []any, boolean string) *Builder
- func (b *Builder) HavingNotNull(columns []any, boolean string) *Builder
- func (b *Builder) HavingNull(columns []any, boolean string, not bool) *Builder
- func (b *Builder) HavingRaw(sql string, bindings ...any) *Builder
- func (b *Builder) IgnoreIndex(index string) *Builder
- func (b *Builder) Implode(ctx context.Context, g auth.Grant, column any, glue string) (string, error)
- func (b *Builder) InRandomOrder(seed ...string) *Builder
- func (b *Builder) Increment(ctx context.Context, g auth.Grant, column string, amount float64, ...) (int64, error)
- func (b *Builder) IncrementEach(ctx context.Context, g auth.Grant, columns map[string]float64, ...) (int64, error)
- func (b *Builder) Insert(ctx context.Context, g auth.Grant, values ...map[string]any) (bool, error)
- func (b *Builder) InsertGetID(ctx context.Context, g auth.Grant, values map[string]any, sequence string) (int64, error)
- func (b *Builder) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (int64, error)
- func (b *Builder) InsertOrIgnoreReturning(ctx context.Context, g auth.Grant, values []map[string]any, ...) ([]Record, error)
- func (b *Builder) InsertOrIgnoreUsing(ctx context.Context, g auth.Grant, columns []any, query any) (int64, error)
- func (b *Builder) InsertUsing(ctx context.Context, g auth.Grant, columns []any, query any) (int64, error)
- func (b *Builder) Join(table any, first any, args ...any) *Builder
- func (b *Builder) JoinLateral(query any, as string, typ string) *Builder
- func (b *Builder) JoinSub(query any, as string, first any, operator, second any, typ string, ...) *Builder
- func (b *Builder) JoinWhere(table any, first any, operator, second any, typ string) *Builder
- func (b *Builder) Latest(column ...any) *Builder
- func (b *Builder) Lazy(ctx context.Context, g auth.Grant, chunkSize int) iter.Seq2[Record, error]
- func (b *Builder) LazyById(ctx context.Context, g auth.Grant, chunkSize int, column, alias string) iter.Seq2[Record, error]
- func (b *Builder) LazyByIdDesc(ctx context.Context, g auth.Grant, chunkSize int, column, alias string) iter.Seq2[Record, error]
- func (b *Builder) LeftJoin(table any, first any, args ...any) *Builder
- func (b *Builder) LeftJoinLateral(query any, as string) *Builder
- func (b *Builder) LeftJoinSub(query any, as string, first any, operator, second any) *Builder
- func (b *Builder) LeftJoinWhere(table any, first any, operator, second any) *Builder
- func (b *Builder) Limit(value int) *Builder
- func (b *Builder) Lock(value any) *Builder
- func (b *Builder) LockForUpdate() *Builder
- func (b *Builder) Max(ctx context.Context, g auth.Grant, column any) (any, error)
- func (b *Builder) MergeBindings(query *Builder) *Builder
- func (b *Builder) MergeWheres(wheres []Where, bindings []any) *Builder
- func (b *Builder) Min(ctx context.Context, g auth.Grant, column any) (any, error)
- func (b *Builder) NewQuery() *Builder
- func (b *Builder) NumericAggregate(ctx context.Context, g auth.Grant, function string, columns ...any) (float64, error)
- func (b *Builder) Offset(value int) *Builder
- func (b *Builder) Oldest(column ...any) *Builder
- func (b *Builder) OrHaving(column any, args ...any) *Builder
- func (b *Builder) OrHavingBetween(column any, values []any) *Builder
- func (b *Builder) OrHavingNotBetween(column any, values []any) *Builder
- func (b *Builder) OrHavingNotNull(columns ...any) *Builder
- func (b *Builder) OrHavingNull(columns ...any) *Builder
- func (b *Builder) OrHavingRaw(sql string, bindings ...any) *Builder
- func (b *Builder) OrWhere(column any, args ...any) *Builder
- func (b *Builder) OrWhereAll(columns []any, args ...any) *Builder
- func (b *Builder) OrWhereAny(columns []any, args ...any) *Builder
- func (b *Builder) OrWhereBetween(column any, from, to any) *Builder
- func (b *Builder) OrWhereBetweenColumns(column any, values []any) *Builder
- func (b *Builder) OrWhereColumn(first any, args ...any) *Builder
- func (b *Builder) OrWhereDate(column any, args ...any) *Builder
- func (b *Builder) OrWhereDay(column any, args ...any) *Builder
- func (b *Builder) OrWhereExists(callback func(*Builder), not ...bool) *Builder
- func (b *Builder) OrWhereFullText(columns []any, value any, options map[string]any) *Builder
- func (b *Builder) OrWhereIn(column any, values []any) *Builder
- func (b *Builder) OrWhereIntegerInRaw(column any, values []any) *Builder
- func (b *Builder) OrWhereIntegerNotInRaw(column any, values []any) *Builder
- func (b *Builder) OrWhereJSONContains(column any, value any) *Builder
- func (b *Builder) OrWhereJSONContainsKey(column any) *Builder
- func (b *Builder) OrWhereJSONDoesntContain(column any, value any) *Builder
- func (b *Builder) OrWhereJSONDoesntContainKey(column any) *Builder
- func (b *Builder) OrWhereJSONDoesntOverlap(column any, value any) *Builder
- func (b *Builder) OrWhereJSONLength(column any, args ...any) *Builder
- func (b *Builder) OrWhereJSONOverlaps(column any, value any) *Builder
- func (b *Builder) OrWhereLike(column any, value any, caseSensitive bool) *Builder
- func (b *Builder) OrWhereMonth(column any, args ...any) *Builder
- func (b *Builder) OrWhereNone(columns []any, args ...any) *Builder
- func (b *Builder) OrWhereNotBetween(column any, from, to any) *Builder
- func (b *Builder) OrWhereNotBetweenColumns(column any, values []any) *Builder
- func (b *Builder) OrWhereNotExists(callback func(*Builder)) *Builder
- func (b *Builder) OrWhereNotIn(column any, values []any) *Builder
- func (b *Builder) OrWhereNotLike(column any, value any, caseSensitive bool) *Builder
- func (b *Builder) OrWhereNotNull(columns ...any) *Builder
- func (b *Builder) OrWhereNull(columns ...any) *Builder
- func (b *Builder) OrWhereRaw(sql string, bindings ...any) *Builder
- func (b *Builder) OrWhereRowValues(columns []any, operator string, values []any) *Builder
- func (b *Builder) OrWhereTime(column any, args ...any) *Builder
- func (b *Builder) OrWhereValueBetween(value any, columns []any) *Builder
- func (b *Builder) OrWhereValueNotBetween(value any, columns []any) *Builder
- func (b *Builder) OrWhereVectorDistanceLessThan(column any, vector []float64, maxDistance float64) *Builder
- func (b *Builder) OrWhereYear(column any, args ...any) *Builder
- func (b *Builder) OrderBy(column any, direction ...string) *Builder
- func (b *Builder) OrderByDesc(column any) *Builder
- func (b *Builder) OrderByRaw(sql string, bindings ...any) *Builder
- func (b *Builder) OrderByVectorDistance(column any, vector []float64) *Builder
- func (b *Builder) OrderedChunkById(ctx context.Context, g auth.Grant, count int, ...) (bool, error)
- func (b *Builder) Paginate(ctx context.Context, g auth.Grant, perPage, page int, columns []any, ...) (*pagination.LengthAwarePaginator[Record], error)
- func (b *Builder) Pipe(callback func(*Builder) *Builder) *Builder
- func (b *Builder) Pluck(ctx context.Context, g auth.Grant, column any, key ...any) (values []any, keyed map[string]any, err error)
- func (b *Builder) PrepareValueAndOperator(value, operator any, useDefault bool) (any, string, error)
- func (b *Builder) Raw(value any) Expression
- func (b *Builder) RawValue(ctx context.Context, g auth.Grant, expression string, bindings ...any) (any, error)
- func (b *Builder) Reorder(column any, direction ...string) *Builder
- func (b *Builder) ReorderDesc(column any) *Builder
- func (b *Builder) RightJoin(table any, first any, args ...any) *Builder
- func (b *Builder) RightJoinSub(query any, as string, first any, operator, second any) *Builder
- func (b *Builder) RightJoinWhere(table any, first any, operator, second any) *Builder
- func (b *Builder) ScopeNested(ctx context.Context, g auth.Grant) error
- func (b *Builder) Select(columns ...any) *Builder
- func (b *Builder) SelectExistsSub(query any, as string) *Builder
- func (b *Builder) SelectExpression(expression any, as string) *Builder
- func (b *Builder) SelectRaw(expression string, bindings ...any) *Builder
- func (b *Builder) SelectSub(query any, as string) *Builder
- func (b *Builder) SelectVectorDistance(column any, vector []float64, as string) *Builder
- func (b *Builder) SetAggregate(function string, columns []any) *Builder
- func (b *Builder) SetBindings(bindings []any, typ string) *Builder
- func (b *Builder) SharedLock() *Builder
- func (b *Builder) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, columns []any, ...) (*pagination.Paginator[Record], error)
- func (b *Builder) Skip(value int) *Builder
- func (b *Builder) Sole(ctx context.Context, g auth.Grant, columns ...any) (Record, error)
- func (b *Builder) SoleValue(ctx context.Context, g auth.Grant, column any) (any, error)
- func (b *Builder) StraightJoin(table any, first any, operator, second any) *Builder
- func (b *Builder) StraightJoinSub(query any, as string, first any, operator, second any) *Builder
- func (b *Builder) StraightJoinWhere(table any, first any, operator, second any) *Builder
- func (b *Builder) Sum(ctx context.Context, g auth.Grant, column any) (any, error)
- func (b *Builder) Take(value int) *Builder
- func (b *Builder) Tap(callback func(*Builder)) *Builder
- func (b *Builder) Timeout(seconds int) *Builder
- func (b *Builder) ToRawSQL(ctx context.Context, g auth.Grant) (string, error)
- func (b *Builder) ToSQL() string
- func (b *Builder) Truncate(ctx context.Context, g auth.Grant) error
- func (b *Builder) Union(query *Builder, all ...bool) *Builder
- func (b *Builder) UnionAll(query *Builder) *Builder
- func (b *Builder) Unless(condition bool, callback, otherwise func(*Builder)) *Builder
- func (b *Builder) Update(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)
- func (b *Builder) UpdateFrom(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)
- func (b *Builder) UpdateOrInsert(ctx context.Context, g auth.Grant, attributes, values map[string]any) (bool, error)
- func (b *Builder) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy []string, ...) (int64, error)
- func (b *Builder) UseIndex(index string) *Builder
- func (b *Builder) UseWritePDO() *Builder
- func (b *Builder) UsingWritePDO() bool
- func (b *Builder) ValidateForCompilation() error
- func (b *Builder) ValidateForCompilationWith(compiler Grammar) error
- func (b *Builder) Value(ctx context.Context, g auth.Grant, column any) (any, error)
- func (b *Builder) When(condition bool, callback, otherwise func(*Builder)) *Builder
- func (b *Builder) Where(column any, args ...any) *Builder
- func (b *Builder) WhereAll(columns []any, args ...any) *Builder
- func (b *Builder) WhereAny(columns []any, args ...any) *Builder
- func (b *Builder) WhereBetween(column any, from, to any) *Builder
- func (b *Builder) WhereBetweenColumns(column any, values []any, boolean string, not bool) *Builder
- func (b *Builder) WhereBindings() []any
- func (b *Builder) WhereColumn(first any, args ...any) *Builder
- func (b *Builder) WhereDate(column any, args ...any) *Builder
- func (b *Builder) WhereDay(column any, args ...any) *Builder
- func (b *Builder) WhereExists(callback func(*Builder), boolean string, not bool) *Builder
- func (b *Builder) WhereFullText(columns []any, value any, options map[string]any, boolean string) *Builder
- func (b *Builder) WhereIn(column any, values []any) *Builder
- func (b *Builder) WhereIntegerInRaw(column any, values []any, boolean string, not bool) *Builder
- func (b *Builder) WhereIntegerNotInRaw(column any, values []any, boolean string) *Builder
- func (b *Builder) WhereJSONContains(column any, value any, boolean string, not bool) *Builder
- func (b *Builder) WhereJSONContainsKey(column any, boolean string, not bool) *Builder
- func (b *Builder) WhereJSONDoesntContain(column any, value any, boolean string) *Builder
- func (b *Builder) WhereJSONDoesntContainKey(column any, boolean string) *Builder
- func (b *Builder) WhereJSONDoesntOverlap(column any, value any, boolean string) *Builder
- func (b *Builder) WhereJSONLength(column any, args ...any) *Builder
- func (b *Builder) WhereJSONOverlaps(column any, value any, boolean string, not bool) *Builder
- func (b *Builder) WhereLike(column any, value any, caseSensitive bool, boolean string, not bool) *Builder
- func (b *Builder) WhereMonth(column any, args ...any) *Builder
- func (b *Builder) WhereNested(callback func(*Builder), boolean string) *Builder
- func (b *Builder) WhereNone(columns []any, args ...any) *Builder
- func (b *Builder) WhereNotBetween(column any, from, to any) *Builder
- func (b *Builder) WhereNotBetweenColumns(column any, values []any, boolean string) *Builder
- func (b *Builder) WhereNotIn(column any, values []any) *Builder
- func (b *Builder) WhereNotLike(column any, value any, caseSensitive bool, boolean string) *Builder
- func (b *Builder) WhereNotNull(columns ...any) *Builder
- func (b *Builder) WhereNull(columns ...any) *Builder
- func (b *Builder) WhereRaw(sql string, bindings ...any) *Builder
- func (b *Builder) WhereRowValues(columns []any, operator string, values []any, boolean string) *Builder
- func (b *Builder) WhereSubCount(sub *Builder, operator string, count int, boolean string) *Builder
- func (b *Builder) WhereTime(column any, args ...any) *Builder
- func (b *Builder) WhereValueBetween(value any, columns []any, boolean string, not bool) *Builder
- func (b *Builder) WhereValueNotBetween(value any, columns []any, boolean string) *Builder
- func (b *Builder) WhereVectorDistanceLessThan(column any, vector []float64, maxDistance float64, boolean string) *Builder
- func (b *Builder) WhereVectorSimilarTo(column any, vector []float64, minSimilarity float64, order bool) *Builder
- func (b *Builder) WhereYear(column any, args ...any) *Builder
- type Connection
- type CursorConnection
- type Expression
- type Grammar
- type GroupLimit
- type Having
- type IndexHint
- type InsertOrIgnoreReturningGrammar
- type InsertUsingGrammar
- type InvalidDirectionError
- type InvalidOperatorError
- type JSONContainsGrammar
- type JoinClause
- type LikeBindingGrammar
- type Order
- type PreparesBindings
- type Processor
- type Record
- type Union
- type UpdateFromGrammar
- type Where
Constants ¶
const GroupLimitGroup = "@hesape_group := "
GroupLimitGroup is the prefix of the user-variable assignment the MySQL group-limit compilation puts in the select list, and the second key Get strips.
const GroupLimitRow = "hesape_row"
GroupLimitRow is the alias the group-limit compilation gives its row-number column. Get strips it out of every row, because it is scaffolding of the query rather than data anybody asked for.
It is exported because the grammar that emits the alias and the builder that strips it have to agree on one string, and two spellings of it is a stray column in somebody's result set.
const TenantColumn = "tenant_id"
TenantColumn is the column every statement this package issues is filtered by, and the column every row it writes carries.
It is a constant and not a setting. The tenant comes off the Grant and from nowhere else; a per-query column name would be a second place for it to come from, and the query that got it wrong would still compile, still run, and still return another customer's rows.
Variables ¶
var ( // ErrRecordNotFound is what FirstOrFail returns when nothing matched. ErrRecordNotFound = errors.New("query: no record found for the given query") // ErrRecordsNotFound is what Sole returns when nothing matched. ErrRecordsNotFound = errors.New("query: no records found for the given query") // ErrMultipleRecordsFound is what Sole returns when more than one row // matched. The message carries the count. ErrMultipleRecordsFound = errors.New("query: multiple records found") )
The execution half of the query builder, and the errors it raises.
The errors are declared here for the reason the Connection interface is declared here -- database imports this package, so naming them there would close the cycle.
var ErrInvalidDirection = errors.New("query: invalid order direction")
ErrInvalidDirection is returned when an order-by clause carries a direction that is neither ascending nor descending.
var ErrInvalidOperator = errors.New("query: invalid operator")
ErrInvalidOperator is returned when a non-raw query clause contains an operator the active grammar does not explicitly support.
Functions ¶
func IsExpression ¶
IsExpression reports whether value is an Expression or a *Expression.
Types ¶
type AffectingConnection ¶
type AffectingConnection interface {
// AffectingStatement runs a statement and returns the number of rows
// affected.
AffectingStatement(ctx context.Context, query string, bindings []any) (int64, error)
}
AffectingConnection is the part of a connection that the write half of the builder reaches for and Connection does not declare: the statement that returns a row count.
A connection that does not implement it still works: Update is what the fallback uses, and the count means the same thing.
type Aggregate ¶
Aggregate is the aggregate a Builder is compiled as: the function name and the columns it is applied to.
type BaseGrammar ¶
type BaseGrammar struct {
// contains filtered or unexported fields
}
BaseGrammar is everything a grammar can spell without knowing its dialect.
A driver grammar embeds it and overrides what its dialect spells differently. It is exported because query/grammars has to embed it.
func (*BaseGrammar) Columnize ¶
func (g *BaseGrammar) Columnize(columns []any) string
Columnize quotes a list of columns and joins them with commas.
func (*BaseGrammar) CompileRandom ¶
func (g *BaseGrammar) CompileRandom(seed string) string
CompileRandom compiles a random ordering expression, optionally seeded.
func (*BaseGrammar) CompileSavepoint ¶
func (g *BaseGrammar) CompileSavepoint(name string) string
CompileSavepoint compiles a statement that creates the named savepoint.
func (*BaseGrammar) CompileSavepointRollBack ¶
func (g *BaseGrammar) CompileSavepointRollBack(name string) string
CompileSavepointRollBack compiles a statement that rolls back to the named savepoint.
func (*BaseGrammar) Escape ¶
func (g *BaseGrammar) Escape(value any, binary bool) (string, error)
Escape returns a value escaped for inclusion directly in SQL.
The base grammar has no connection to escape through, so it refuses. A driver grammar that can escape overrides it. This is deliberately not a best-effort quote: a caller reaching for Escape is building SQL by hand, and a value that looks escaped but is not is worse than one that refuses.
func (*BaseGrammar) GetBitwiseOperators ¶
func (g *BaseGrammar) GetBitwiseOperators() []string
GetBitwiseOperators returns the operators treated as bitwise rather than comparison.
func (*BaseGrammar) GetDateFormat ¶
func (g *BaseGrammar) GetDateFormat() string
GetDateFormat returns the layout the engine's date columns are formatted with, in Go's reference-time syntax.
func (*BaseGrammar) GetOperators ¶
func (g *BaseGrammar) GetOperators() []string
GetOperators returns the comparison operators the grammar accepts.
func (*BaseGrammar) GetTablePrefix ¶
func (g *BaseGrammar) GetTablePrefix() string
GetTablePrefix returns the prefix applied to every table name.
func (*BaseGrammar) Parameter ¶
func (g *BaseGrammar) Parameter(value any) string
Parameter returns the placeholder for a value, or the value itself when it is an Expression.
The placeholder is "?". A grammar for an engine that numbers its placeholders overrides this, and overrides it knowing the number comes from the position in the binding list rather than from the value.
func (*BaseGrammar) Parameterize ¶
func (g *BaseGrammar) Parameterize(values []any) string
Parameterize returns the comma-separated placeholders for a list of values.
func (*BaseGrammar) QuoteString ¶
func (g *BaseGrammar) QuoteString(value any) string
QuoteString quotes a string literal, or each one in a list.
func (*BaseGrammar) SetTablePrefix ¶
func (g *BaseGrammar) SetTablePrefix(prefix string) Grammar
SetTablePrefix sets the prefix applied to every table name.
func (*BaseGrammar) SupportsSavepoints ¶
func (g *BaseGrammar) SupportsSavepoints() bool
SupportsSavepoints reports whether the engine can savepoint within a transaction.
func (*BaseGrammar) Wrap ¶
func (g *BaseGrammar) Wrap(value any) string
Wrap quotes an identifier, splitting an aliased name into its two quoted halves.
An Expression passes through untouched, which is the whole reason Expression exists: it is how a caller says "this is SQL, not a name".
func (*BaseGrammar) WrapArray ¶
func (g *BaseGrammar) WrapArray(values []any) []string
WrapArray quotes each value in a list of identifiers.
func (*BaseGrammar) WrapTable ¶
func (g *BaseGrammar) WrapTable(table any) string
WrapTable quotes a table name. The table prefix is applied here and nowhere else, which is why a raw table name in a where clause is a bug that only shows up on a prefixed connection.
type Builder ¶
type Builder struct {
// Grammar is what compiles the query to SQL for a specific engine.
Grammar Grammar
// Processor is the hook that adjusts results as they come back from the
// engine.
Processor Processor
// Bindings holds the query's parameter values, keyed by the seven
// segments of a statement they belong to. The order of the keys is the
// order they are concatenated in, which is why GetBindings walks
// bindingOrder rather than ranging the map.
Bindings map[string][]any
// Columns is the select list. Nil means "not selected yet", which is
// what lets Get default to * while an explicit Select of nothing selects
// nothing.
Columns []any
// Wheres is the list of where clauses.
Wheres []Where
// Joins is the list of join clauses.
Joins []*JoinClause
// Groups is the GROUP BY column list.
Groups []any
// Havings is the list of having clauses.
Havings []Having
// Orders is the list of order-by clauses.
Orders []Order
// Unions is the list of queries unioned onto this one.
Unions []Union
// UnionOrders is the order-by list that applies to the union as a whole.
UnionOrders []Order
// UnionLimit is the limit that applies to the union as a whole.
UnionLimit *int
// UnionOffset is the offset that applies to the union as a whole.
UnionOffset *int
// BeforeQueryCallbacks run immediately before the query is compiled.
BeforeQueryCallbacks []func(*Builder)
// AfterQueryCallbacks each run over the result of Get, Pluck or Cursor
// before it is handed back.
AfterQueryCallbacks []func([]Record) []Record
// contains filtered or unexported fields
}
Builder is the fluent query builder.
It builds SQL and does not decide who may run it. Authorization lives one layer up, in the repository that holds a security.Grant and filters by the tenant that Grant carries -- on reads exactly as on writes. A Builder reached without going through that layer is SQL nobody authorized, which is why nothing outside a repository should be constructing one.
Which fields are exported, and which are read through a getter ¶
The grammar reads the builder's state directly, so the state is exported. Nine of them cannot be: from, limit, offset, distinct, lock, aggregate, timeout, groupLimit and indexHint are all a field AND a fluent method, and Go holds both in one namespace. Those are unexported and reachable through GetFrom, GetLimit, GetOffset, GetColumns, GetDistinct, GetLock, GetAggregate, GetTimeout, GetGroupLimit and GetIndexHint.
func NewBuilder ¶
func NewBuilder(connection Connection, grammar Grammar, processor Processor) *Builder
NewBuilder creates a Builder for the given connection, grammar and processor, with an empty binding slice for each of the seven segments.
func (*Builder) AddBinding ¶
AddBinding appends value to the named binding segment.
An unknown binding type is dropped rather than appended to a key the grammar never reads. The seven names are in bindingOrder and are not open to extension.
func (*Builder) AddNestedHavingQuery ¶
AddNestedHavingQuery folds query's havings into b as one parenthesised group.
A group with no clauses is dropped rather than compiled, for the reason AddNestedWhereQuery gives: "()" is a syntax error on every engine, and an empty callback is an ordinary outcome of a conditional filter.
func (*Builder) AddNestedWhereQuery ¶
AddNestedWhereQuery adds query as a parenthesised group of clauses under boolean.
A group with no clauses is dropped rather than compiled, because "()" is a syntax error on every engine and an empty callback is an ordinary outcome of a conditional filter.
func (*Builder) AddWhereExistsQuery ¶
AddWhereExistsQuery adds query as an exists (or not-exists) clause under boolean.
func (*Builder) AfterQuery ¶
AfterQuery registers a callback to run over the result after the query executes.
func (*Builder) Aggregate ¶
func (b *Builder) Aggregate(ctx context.Context, g auth.Grant, function string, columns ...any) (any, error)
Aggregate runs an aggregate function over columns and returns the engine's raw result.
The result is whatever the engine returned for the aggregate column -- an int64, a float64, a string or a []byte, depending on the driver and the function. Count and NumericAggregate are the two that commit to a Go type. A nil result means the query matched nothing, which for min and max is the answer rather than an error.
func (*Builder) ApplyAfterQueryCallbacks ¶
ApplyAfterQueryCallbacks runs every registered AfterQuery callback over result. Each callback receives what the one before it returned, so they compose.
func (*Builder) ApplyBeforeQueryCallbacks ¶
func (b *Builder) ApplyBeforeQueryCallbacks()
ApplyBeforeQueryCallbacks drains registered callbacks across the complete query graph, then validates every non-raw operator and order direction. Callbacks registered by callbacks are part of the same preparation and cannot run midway through SQL compilation. A callback cycle fails closed after a bounded number of rounds.
func (*Builder) BeforeQuery ¶
BeforeQuery registers a callback to run immediately before the query is compiled.
func (*Builder) CastBinding ¶
CastBinding returns value unchanged.
A named type over a scalar is already seen by the driver as the scalar, so there is nothing to unwrap. It stays because it is the one place a future cast would go, and because a caller looking for it should find it rather than conclude it is missing.
func (*Builder) Chunk ¶
func (b *Builder) Chunk(ctx context.Context, g auth.Grant, count int, callback func(rows []Record, page int) bool) (bool, error)
Chunk walks the result set by offset, a page at a time, and stops when the callback returns false.
This is the chunking that skips rows. Between two pages the table can change, and every insert before the offset shifts a row past the boundary that was already read. ChunkById does not have that failure, and is what to reach for on a table that is being written to.
A limit or an offset already on the query is honoured: the offset is where the walk starts, and the limit is how many rows it reads in total.
func (*Builder) ChunkById ¶
func (b *Builder) ChunkById(ctx context.Context, g auth.Grant, count int, callback func(rows []Record, page int) bool, column, alias string) (bool, error)
ChunkById is the chunk that does not skip rows.
Instead of counting rows to reach page n, each page asks for the rows after the last id of the page before it, so an insert or a delete anywhere in the table moves no boundary. It is the one to use for anything that walks a table while the application is running.
An empty column means the id. alias is the name that column comes back under when the select renames it -- give it whenever the query selects the key column under another name, because the walk reads the boundary out of the row by that name, and a boundary it cannot read stops the walk with an error rather than silently repeating the first page forever.
func (*Builder) ChunkByIdDesc ¶
func (b *Builder) ChunkByIdDesc(ctx context.Context, g auth.Grant, count int, callback func(rows []Record, page int) bool, column, alias string) (bool, error)
ChunkByIdDesc is ChunkById walking from the highest id down.
func (*Builder) ChunkMap ¶
func (b *Builder) ChunkMap(ctx context.Context, g auth.Grant, callback func(row Record) any, count int) ([]any, error)
ChunkMap chunks the query and runs callback over every row, collecting the results into a single slice.
The return type is any rather than a type parameter: a method in Go cannot introduce a type parameter of its own, and making this a function instead of a method would take it out of the chain it is written in.
func (*Builder) CleanBindings ¶
CleanBindings drops the expressions from bindings, which were compiled into the statement and have no placeholder to fill.
func (*Builder) Clone ¶
Clone returns a copy of the builder.
The slices and the binding map are copied, so a clone that gains a where does not grow one on the query it was cloned from. That sharing is the bug behind every "the count query has the pagination limit on it" report.
func (*Builder) CloneWithout ¶
CloneWithout returns a clone with the named properties reset to their zero value.
func (*Builder) CloneWithoutBindings ¶
CloneWithoutBindings returns a clone with the named binding segments cleared.
func (*Builder) CrossJoin ¶
CrossJoin adds a cross join. With no condition it is a bare cross join; with one it compiles as an inner join.
func (*Builder) CrossJoinSub ¶
CrossJoinSub is a cross join against a subquery, which has no condition at all.
A cross join multiplies the rows of both sides, so the subquery is the whole of what the join contributes: without a tenant filter of its own it would pair this customer's rows with every customer's. It gets one in scopeSubqueryClauses, like every other subquery here.
func (*Builder) Cursor ¶
Cursor streams the query's rows one at a time, without loading the result set into memory.
It is the one read that does not materialise its rows: the connection hands them over one at a time, and nothing here holds more than the row being yielded. That needs a connection that can stream, which is CursorConnection; a connection without it gets an error rather than a select that quietly reads the whole table into memory.
func (*Builder) CursorPaginate ¶
func (b *Builder) CursorPaginate(ctx context.Context, g auth.Grant, perPage int, cursor *pagination.Cursor, columns []any, opts pagination.Options) (*pagination.CursorPaginator[Record], error)
CursorPaginate pages through the query using a keyset cursor instead of an offset.
The cursor is resolved by the caller -- pagination.ResolveCurrentCursor reads it off a URL -- because no request is reachable from here. A nil cursor is the first page.
func (*Builder) Decrement ¶
func (b *Builder) Decrement(ctx context.Context, g auth.Grant, column string, amount float64, extra map[string]any) (int64, error)
Decrement subtracts amount from column. See Increment.
func (*Builder) DecrementEach ¶
func (b *Builder) DecrementEach(ctx context.Context, g auth.Grant, columns map[string]float64, extra map[string]any) (int64, error)
DecrementEach subtracts separate amounts from multiple columns, along with any extra columns to set.
func (*Builder) Delete ¶
Delete deletes the rows matching the query.
The optional id, when given, adds a where on the primary key, so that a single row can be removed without writing one.
func (*Builder) Distinct ¶
Distinct marks the query as distinct.
With no argument it is a plain DISTINCT; with columns it is the engine's DISTINCT ON, which only Postgres compiles.
func (*Builder) DoesntExist ¶
DoesntExist reports whether the query matches no rows.
func (*Builder) DoesntExistOr ¶
func (b *Builder) DoesntExistOr(ctx context.Context, g auth.Grant, callback func() error) (bool, error)
DoesntExistOr reports whether the query matches no rows, running callback when rows do exist. The bool is read as ExistsOr's is.
func (*Builder) Dump ¶
Dump writes the statement and its bindings, and hands the query back so the chain continues.
The destination is an argument, as it is on DumpRawSQL.
What it prints is the query as written, without the tenant filter, because the filter belongs to the statement and not to the builder. DumpRawSQL takes a Grant and prints what would actually run.
func (*Builder) DumpRawSQL ¶
DumpRawSQL writes the statement with its bindings substituted in.
The destination is an argument, and a failed substitution is written out too -- a dump that printed nothing and returned would be the least helpful debugging tool there is.
func (*Builder) DynamicWhere ¶
DynamicWhere reads a where clause out of a method name, as in "whereNameAndEmail", and binds the values positionally.
The name is an argument rather than something dispatched to, so a caller with a column list coming from configuration has one string to turn into clauses.
func (*Builder) Each ¶
func (b *Builder) Each(ctx context.Context, g auth.Grant, callback func(row Record, index int) bool, count int) (bool, error)
Each chunks the query and runs callback over every row, passing each row's position inside its own chunk as the index.
EachById counts from the start of the walk instead, and the difference is deliberate in both.
func (*Builder) EachById ¶
func (b *Builder) EachById(ctx context.Context, g auth.Grant, callback func(row Record, index int) bool, count int, column, alias string) (bool, error)
EachById chunks the query by id and runs callback over every row, passing each row's position since the start of the walk as the index.
The index counts from the start of the walk, not from the start of the chunk: it is (page-1)*count + i, computed from the page ChunkById reports and the row's position inside it.
func (*Builder) Err ¶ added in v0.22.0
Err returns the first final-validation error recorded by the builder or one of its child queries.
func (*Builder) Exists ¶
Exists reports whether the query matches at least one row.
It compiles to the grammar's exists statement -- a select wrapped so the engine can stop at the first row -- rather than counting.
func (*Builder) ExistsOr ¶
ExistsOr reports whether the query matches at least one row, running callback when it does not.
The bool is the answer to the question -- did rows exist -- and the callback contributes only its error, because a callback that returned a value would have to return the same type as `true`.
func (*Builder) Find ¶
Find adds an id filter and returns the first matching row.
It adds the where to the builder it is called on, so calling it twice with two ids asks for a row that is both.
func (*Builder) FindOr ¶
func (b *Builder) FindOr(ctx context.Context, g auth.Grant, id any, columns []any, callback func() (Record, error)) (Record, error)
FindOr adds an id filter and returns the first matching row, or the result of callback if none matched. The columns may be nil.
func (*Builder) First ¶
First returns the first row the query matches, or nil if none did.
A nil Record means no row matched. The error is for a statement that failed, which is a different outcome and reads differently at the call site.
func (*Builder) FirstOr ¶
func (b *Builder) FirstOr(ctx context.Context, g auth.Grant, columns []any, callback func() (Record, error)) (Record, error)
FirstOr returns the first row the query matches, or the result of callback if none did. It is the sibling of FindOr, spelled out here as well so that the two read the same and a caller who reaches for one finds the other.
The result is a Record rather than a type parameter of the callback's own choosing: a method cannot declare type parameters beyond what its receiver already has, and *Builder has none.
func (*Builder) FirstOrFail ¶
func (b *Builder) FirstOrFail(ctx context.Context, g auth.Grant, columns []any, message ...string) (Record, error)
FirstOrFail returns the first row the query matches, or an error if none did.
The message is a variadic string wrapping ErrRecordNotFound, so errors.Is still recognises it however it was worded.
func (*Builder) ForNestedWhere ¶
ForNestedWhere returns a new query sharing this one's table, for building a nested group of clauses.
func (*Builder) ForPage ¶
ForPage sets the limit and offset for the given page of results.
It is offset pagination, and it is the wrong tool past the first few pages: the engine counts and discards every row it skips, and a row inserted between two requests shifts the boundary so that a row is never shown. CursorPaginate in the pagination package names the boundary by value instead.
func (*Builder) ForPageAfterId ¶
ForPageAfterId narrows the query to the next page of results after a given id.
The existing ordering on that column is dropped and the column is ordered by again, last: the boundary is only a boundary if the rows come back in the order the boundary was taken from. Other orderings are kept, and the id becomes their tiebreaker.
A nil lastId is the first page, and asks for the column not to be null -- a null id can never be compared past, so a row holding one would be returned by every page.
func (*Builder) ForPageBeforeId ¶
ForPageBeforeId narrows the query to the previous page of results before a given id. See ForPageAfterId.
func (*Builder) ForceIndex ¶
ForceIndex hints the engine to force the named index.
func (*Builder) From ¶
From sets the table the query reads from. The table may be a string or an Expression.
func (*Builder) Get ¶
Get runs the query and returns its rows.
The columns are variadic and default to every column; they only apply when nothing was selected already. They are set on the scoped copy the tenant clause is added to, so the builder the caller holds is never mutated.
func (*Builder) GetAggregate ¶
GetAggregate returns the aggregate being compiled, if any. Mechanical, for the same reason as GetFrom.
func (*Builder) GetBindings ¶
GetBindings returns every binding, flattened in the order the compiled statement consumes them.
func (*Builder) GetColumns ¶
GetColumns returns the select list, with any Expression rendered to the SQL it carries rather than returned as the object.
It returns an empty slice rather than nil when nothing was selected, so a caller ranging the result never has to special-case nil.
func (*Builder) GetConnection ¶
func (b *Builder) GetConnection() Connection
GetConnection returns the connection the query runs against.
func (*Builder) GetCountForPagination ¶
func (b *Builder) GetCountForPagination(ctx context.Context, g auth.Grant, columns ...any) (int, error)
GetCountForPagination returns the total number of rows the query matches, ignoring any limit or offset.
func (*Builder) GetDistinct ¶
GetDistinct returns the DISTINCT state: false, true, or the columns of a DISTINCT ON. Mechanical, for the same reason as GetFrom.
func (*Builder) GetFrom ¶
GetFrom returns the table the query reads from.
The fluent From method claimed the name "from" in Go's single namespace, so the underlying state is unexported and reachable only through this getter.
func (*Builder) GetGrammar ¶
GetGrammar returns the grammar the query compiles through.
func (*Builder) GetGroupLimit ¶
func (b *Builder) GetGroupLimit() *GroupLimit
GetGroupLimit returns the per-group limit, if one was set. Mechanical, for the same reason as GetFrom.
func (*Builder) GetIndexHint ¶
GetIndexHint returns the index hint, if one was set. Mechanical, for the same reason as GetFrom.
func (*Builder) GetLimit ¶
GetLimit returns the row limit, if one was set. Mechanical, for the same reason as GetFrom.
func (*Builder) GetLock ¶
GetLock returns the lock state. Mechanical, for the same reason as GetFrom.
func (*Builder) GetOffset ¶
GetOffset returns the row offset, if one was set. Mechanical, for the same reason as GetFrom.
func (*Builder) GetProcessor ¶
GetProcessor returns the processor that adjusts the query's results.
func (*Builder) GetRawBindings ¶
GetRawBindings returns the bindings keyed by segment, unflattened.
func (*Builder) GetTimeout ¶
GetTimeout returns the statement timeout in seconds, if one was set. Mechanical, for the same reason as GetFrom.
func (*Builder) GroupByRaw ¶
GroupByRaw adds a raw expression to the GROUP BY list, with its own bindings.
func (*Builder) GroupLimit ¶
GroupLimit limits the number of rows per group of column, for a "top N per group" query.
func (*Builder) Having ¶
Having adds a having clause. The body is in havings.go, shared with OrHaving: the two differ by their conjunction and by nothing else.
func (*Builder) HavingBetween ¶
HavingBetween adds a having that requires column to fall between the first two values, or outside them when not is true.
Only the first two values are bound: a between has two bounds, and a longer list is a caller mistake that would otherwise leave bindings with no placeholder to fill.
func (*Builder) HavingNested ¶
HavingNested runs callback against a fresh nested query and folds its havings in as one parenthesised group.
func (*Builder) HavingNotBetween ¶
HavingNotBetween is HavingBetween with not set to true.
func (*Builder) HavingNotNull ¶
HavingNotNull is HavingNull with not set to true.
func (*Builder) HavingNull ¶
HavingNull adds a having that requires columns to be null, or not null when not is true.
func (*Builder) IgnoreIndex ¶
IgnoreIndex hints the engine to ignore the named index.
func (*Builder) Implode ¶
func (b *Builder) Implode(ctx context.Context, g auth.Grant, column any, glue string) (string, error)
Implode plucks column across every matching row and joins the values with glue.
func (*Builder) InRandomOrder ¶
InRandomOrder orders the results randomly, optionally seeded.
func (*Builder) Increment ¶
func (b *Builder) Increment(ctx context.Context, g auth.Grant, column string, amount float64, extra map[string]any) (int64, error)
Increment adds amount to column, along with any extra columns to set.
A non-numeric amount does not compile: Go's float64 parameter type enforces that guarantee at the call site, before the query ever runs.
extra is the columns to set alongside, and may be nil.
func (*Builder) IncrementEach ¶
func (b *Builder) IncrementEach(ctx context.Context, g auth.Grant, columns map[string]float64, extra map[string]any) (int64, error)
IncrementEach adds separate amounts to multiple columns, along with any extra columns to set.
func (*Builder) Insert ¶
Insert inserts one row or many.
Variadic arguments accept either shape directly, without needing to inspect whether the caller passed one row or a list.
The rows are copied before the tenant is stamped into them, so a caller's map does not gain a column it never asked for.
func (*Builder) InsertGetID ¶
func (b *Builder) InsertGetID(ctx context.Context, g auth.Grant, values map[string]any, sequence string) (int64, error)
InsertGetID inserts a row and returns the id the engine assigned it.
sequence is the name of the sequence the id comes from, which Postgres needs and the other engines ignore. Empty means the engine's default.
func (*Builder) InsertOrIgnore ¶
func (b *Builder) InsertOrIgnore(ctx context.Context, g auth.Grant, values ...map[string]any) (int64, error)
InsertOrIgnore inserts rows, letting the engine drop the ones that would violate a unique constraint, and returns how many it kept.
func (*Builder) InsertOrIgnoreReturning ¶
func (b *Builder) InsertOrIgnoreReturning(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy, returning []string) ([]Record, error)
InsertOrIgnoreReturning inserts rows, letting the engine drop the ones that would collide, and returns the rows it kept rather than a count.
The rows carry the tenant of the Grant, as every insert here does, and the statement goes to the write connection: the rows it returns were written microseconds ago and a replica has not seen them.
func (*Builder) InsertOrIgnoreUsing ¶
func (b *Builder) InsertOrIgnoreUsing(ctx context.Context, g auth.Grant, columns []any, query any) (int64, error)
InsertOrIgnoreUsing is InsertUsing letting the engine drop the rows that would collide.
func (*Builder) InsertUsing ¶
func (b *Builder) InsertUsing(ctx context.Context, g auth.Grant, columns []any, query any) (int64, error)
InsertUsing is an insert whose rows come from a select rather than from values.
query may be a *Builder, a func(*Builder) or a string of SQL. A *Builder or a callback is scoped by the same Grant before it is compiled -- an insert reading from a select is a read, and a read that skipped the tenant would copy another customer's rows into this one's table.
A string is taken as written. Nothing here can add a tenant filter to SQL it did not build, which is the reason to hand it a builder instead.
func (*Builder) JoinLateral ¶
JoinLateral joins against a subquery that may name the columns of the rows already joined.
func (*Builder) JoinSub ¶
func (b *Builder) JoinSub(query any, as string, first any, operator, second any, typ string, isWhere bool) *Builder
JoinSub joins against a subquery.
typ is the join type -- inner, left, right, cross or straight_join -- and isWhere says whether the condition compares a column with a value rather than with another column.
func (*Builder) Latest ¶
Latest adds a descending order-by clause. The column defaults to created_at.
func (*Builder) Lazy ¶
Lazy walks the result set by offset, a page at a time, and returns an iter.Seq2 that yields one row at a time without materialising the whole result set.
The second value is the error, because a walk that fails halfway has nowhere else to report it and a sequence that just stopped early would read as "the table ended here" -- which is the same answer as success and is why this is not a Seq of rows.
The sequence walks by offset and skips rows for the reason Chunk does. LazyById is the one that holds still.
func (*Builder) LazyById ¶
func (b *Builder) LazyById(ctx context.Context, g auth.Grant, chunkSize int, column, alias string) iter.Seq2[Record, error]
LazyById is Lazy walking by key instead of by offset, so that a table written to during the walk neither repeats a row nor skips one.
func (*Builder) LazyByIdDesc ¶
func (b *Builder) LazyByIdDesc(ctx context.Context, g auth.Grant, chunkSize int, column, alias string) iter.Seq2[Record, error]
LazyByIdDesc is LazyById walking from the highest id down.
func (*Builder) LeftJoinLateral ¶
LeftJoinLateral is JoinLateral with typ set to "left".
func (*Builder) LeftJoinSub ¶
LeftJoinSub is JoinSub with typ set to "left".
func (*Builder) LeftJoinWhere ¶
LeftJoinWhere is JoinWhere with typ set to "left".
func (*Builder) LockForUpdate ¶
LockForUpdate locks the selected rows for update.
func (*Builder) MergeBindings ¶
MergeBindings appends query's bindings onto this builder's, segment by segment.
func (*Builder) MergeWheres ¶
MergeWheres appends another query's where clauses and bindings onto this one.
The bindings are appended to the where segment as given. They are the caller's to line up with the clauses: the two arguments are the two halves of somebody else's query, and nothing here can check that they match.
func (*Builder) NewQuery ¶
NewQuery returns a new Builder sharing this one's connection, grammar and processor.
func (*Builder) NumericAggregate ¶
func (b *Builder) NumericAggregate(ctx context.Context, g auth.Grant, function string, columns ...any) (float64, error)
NumericAggregate runs an aggregate function and casts the result to a number.
It returns a float64 rather than committing to int or float depending on the driver's answer: Go has one number type that holds both, and nothing is lost -- an int64 that survives a float64 round trip is every count a database will produce short of 2^53 rows.
func (*Builder) Oldest ¶
Oldest adds an ascending order-by clause. The column defaults to created_at.
func (*Builder) OrHavingBetween ¶
OrHavingBetween is HavingBetween joined with "or".
func (*Builder) OrHavingNotBetween ¶
OrHavingNotBetween is HavingBetween joined with "or" and not set to true.
func (*Builder) OrHavingNotNull ¶
OrHavingNotNull is HavingNotNull joined with "or".
func (*Builder) OrHavingNull ¶
OrHavingNull is HavingNull joined with "or".
func (*Builder) OrHavingRaw ¶
OrHavingRaw adds a raw having clause joined with "or".
func (*Builder) OrWhereAll ¶
OrWhereAll adds an "or" version of WhereAll.
func (*Builder) OrWhereAny ¶
OrWhereAny adds an "or" version of WhereAny.
func (*Builder) OrWhereBetween ¶
OrWhereBetween adds an "or" between clause.
func (*Builder) OrWhereBetweenColumns ¶
OrWhereBetweenColumns adds an "or" between-columns clause.
func (*Builder) OrWhereColumn ¶
OrWhereColumn adds an "or" clause comparing two columns.
func (*Builder) OrWhereDate ¶
OrWhereDate adds an "or" date clause.
func (*Builder) OrWhereDay ¶
OrWhereDay adds an "or" day clause.
func (*Builder) OrWhereExists ¶
OrWhereExists adds an "or exists" clause for the subquery the callback builds, optionally negated.
func (*Builder) OrWhereFullText ¶
OrWhereFullText adds an "or" full-text search clause.
func (*Builder) OrWhereIntegerInRaw ¶
OrWhereIntegerInRaw adds an "or" where-in clause with raw integer values.
func (*Builder) OrWhereIntegerNotInRaw ¶
OrWhereIntegerNotInRaw adds an "or" where-not-in clause with raw integer values.
func (*Builder) OrWhereJSONContains ¶
OrWhereJSONContains adds an "or" JSON-contains clause.
func (*Builder) OrWhereJSONContainsKey ¶
OrWhereJSONContainsKey adds an "or" JSON-contains-key clause.
func (*Builder) OrWhereJSONDoesntContain ¶
OrWhereJSONDoesntContain adds an "or" JSON-does-not-contain clause.
func (*Builder) OrWhereJSONDoesntContainKey ¶
OrWhereJSONDoesntContainKey adds an "or" JSON-does-not-contain-key clause.
func (*Builder) OrWhereJSONDoesntOverlap ¶
OrWhereJSONDoesntOverlap adds an "or" JSON-does-not-overlap clause.
func (*Builder) OrWhereJSONLength ¶
OrWhereJSONLength adds an "or" JSON-length clause.
func (*Builder) OrWhereJSONOverlaps ¶
OrWhereJSONOverlaps adds an "or" JSON-overlaps clause.
func (*Builder) OrWhereLike ¶
OrWhereLike adds an "or" LIKE clause.
func (*Builder) OrWhereMonth ¶
OrWhereMonth adds an "or" month clause.
func (*Builder) OrWhereNone ¶
OrWhereNone adds an "or" version of WhereNone.
func (*Builder) OrWhereNotBetween ¶
OrWhereNotBetween adds an "or" not-between clause.
func (*Builder) OrWhereNotBetweenColumns ¶
OrWhereNotBetweenColumns adds an "or" not-between-columns clause.
func (*Builder) OrWhereNotExists ¶
OrWhereNotExists adds an "or not exists" clause for the subquery the callback builds.
func (*Builder) OrWhereNotIn ¶
OrWhereNotIn adds an "or" where-not-in clause.
func (*Builder) OrWhereNotLike ¶
OrWhereNotLike adds an "or" NOT LIKE clause.
func (*Builder) OrWhereNotNull ¶
OrWhereNotNull adds an "or" is-not-NULL clause.
func (*Builder) OrWhereNull ¶
OrWhereNull adds an "or" is-NULL clause.
func (*Builder) OrWhereRaw ¶
OrWhereRaw adds an "or" raw SQL where clause.
func (*Builder) OrWhereRowValues ¶
OrWhereRowValues adds an "or" row-values clause.
func (*Builder) OrWhereTime ¶
OrWhereTime adds an "or" time clause.
func (*Builder) OrWhereValueBetween ¶
OrWhereValueBetween adds an "or" value-between-columns clause.
func (*Builder) OrWhereValueNotBetween ¶
OrWhereValueNotBetween adds an "or" value-not-between-columns clause.
func (*Builder) OrWhereVectorDistanceLessThan ¶
func (b *Builder) OrWhereVectorDistanceLessThan(column any, vector []float64, maxDistance float64) *Builder
OrWhereVectorDistanceLessThan adds an "or" vector-distance clause.
func (*Builder) OrWhereYear ¶
OrWhereYear adds an "or" year clause.
func (*Builder) OrderBy ¶
OrderBy adds an order-by clause. A direction other than asc or desc is a caller writing SQL into a direction, so anything else reads as asc.
func (*Builder) OrderByDesc ¶
OrderByDesc adds a descending order-by clause.
func (*Builder) OrderByRaw ¶
OrderByRaw adds a raw order-by expression, with its own bindings.
func (*Builder) OrderByVectorDistance ¶
OrderByVectorDistance orders by the distance between a column's embedding and the vector given, nearest first.
func (*Builder) OrderedChunkById ¶
func (b *Builder) OrderedChunkById(ctx context.Context, g auth.Grant, count int, callback func(rows []Record, page int) bool, column, alias string, descending bool) (bool, error)
OrderedChunkById is the shared body of ChunkById and ChunkByIdDesc.
Each page runs on a copy of the query, because ForPageAfterId adds a where and rewrites the ordering: applying that to the query itself would leave the previous page's boundary on the next page's statement, and the walk would stand still.
An offset already on the query applies to the first page only. After that the id boundary is doing the skipping, and skipping again would drop a page's worth of rows on every page.
func (*Builder) Paginate ¶
func (b *Builder) Paginate(ctx context.Context, g auth.Grant, perPage, page int, columns []any, opts pagination.Options, total ...int) (*pagination.LengthAwarePaginator[Record], error)
Paginate runs the query for one page and returns a length-aware paginator.
No request is reachable from here, so the page number is an argument and the path is a field of pagination.Options, along with the name of the page parameter.
total is a count the caller already has. Leaving it out runs GetCountForPagination, which is one extra statement -- the one SimplePaginate exists to avoid.
func (*Builder) Pipe ¶
Pipe hands the query to callback, and returns what callback returned, or the query itself if callback returned nil.
func (*Builder) Pluck ¶
func (b *Builder) Pluck(ctx context.Context, g auth.Grant, column any, key ...any) (values []any, keyed map[string]any, err error)
Pluck returns the values of column across every matching row, in row order, and -- only when a key column is named -- the same values keyed by it. keyed is nil when no key column was given.
The keys are always strings: a key value is formatted to a string on the way in, whatever type it arrived as.
func (*Builder) PrepareValueAndOperator ¶
func (b *Builder) PrepareValueAndOperator(value, operator any, useDefault bool) (any, string, error)
PrepareValueAndOperator resolves the value and operator for a where clause that may have been built from two arguments or three.
When useDefault is true, operator is treated as the value and the comparison operator defaults to "="; otherwise value and operator are returned as given, after checking the combination.
It returns an error for the combination it refuses: an operator with no value, such as where('votes', '>'), which would otherwise compile to a comparison against NULL and quietly match nothing.
The fluent methods do not call it; they use the unexported prepareValueAndOperator, which reads the same two-or-three-argument distinction off the length of a variadic slice. This one is exported because a caller assembling an operator and a value from user input has the same combination to validate.
It screens and reports; it does not record the refusal on the builder. A caller validating a combination is expected to handle the error and fall back to something safe, and a builder that had been disabled by the question would drop every clause added after it. Nothing is given up by staying quiet: the operator returned here is not what reaches SQL. Where, Having and On screen what they are given, and the final barrier screens the whole graph again against the compiling grammar before a statement is built.
func (*Builder) Raw ¶
func (b *Builder) Raw(value any) Expression
Raw returns value wrapped as an Expression.
It is a method on Builder for symmetry with the fluent chain; Raw is the package function that actually builds one.
func (*Builder) RawValue ¶
func (b *Builder) RawValue(ctx context.Context, g auth.Grant, expression string, bindings ...any) (any, error)
RawValue returns the value of a raw expression from the query's first matching row.
Alias the expression -- rawValue("count(*) as total") -- when the query already selects something: a Go map has no first column, so the alias is the name the value is found under.
func (*Builder) Reorder ¶
Reorder drops every order-by clause, and adds one back when given a column. Pass nil to drop the ordering and add nothing.
func (*Builder) ReorderDesc ¶
ReorderDesc drops every order-by clause and adds one back in descending order.
func (*Builder) RightJoinSub ¶
RightJoinSub is JoinSub with typ set to "right".
func (*Builder) RightJoinWhere ¶
RightJoinWhere is JoinWhere with typ set to "right".
func (*Builder) ScopeNested ¶
ScopeNested puts the tenant on every query nested inside this one: the far side of a union, the subquery of a `where exists`, of a `where in` and of a count comparison, and the subqueries compiled into a from, a select or a join.
It is the second half of scoped, and it is exported because it is the half the model builder has to end in too. That builder cannot call scoped whole: it filters by the model's own tenant column, which a model whose table has none sets to the empty string, and TenantColumn here is a constant on purpose -- see its comment. The nested half has no such difference, and it is where every leak found so far lived, so there is one of it and both builders run it.
Until it was exported the model builder reached none of it. GetModels sent b.query.ToSQL() straight to the connection, so scopeUnions, scopeSubqueries and scopeSubqueryClauses were dead code on the path the application uses: Users.WithCount("posts").Get(g) came back with every tenant's posts counted into posts_count, and WhereHas("posts", ...) filtered one tenant's users by another tenant's rows.
It runs on the statement being built and never on the builder the caller holds -- scoped calls it on a clone, and the model builder on the clone ApplyScopes made.
func (*Builder) Select ¶
Select sets the columns to select, replacing any previous selection. AddSelect is how a column is appended instead.
func (*Builder) SelectExistsSub ¶
SelectExistsSub is SelectSub for a subquery asked as a yes or no: it compiles to `exists (select ...) as alias`.
The model builder's WithExists used to write the whole column as raw SQL, which is a subquery nothing can scope afterwards -- and that is what Users.WithExists("posts").Get(g) proved: the column asked whether ANY tenant had a post for that user. This is selectSub with the one operator that column needs, so the exists form goes through the same bookkeeping every other subquery does. See pendingSub.
func (*Builder) SelectExpression ¶
SelectExpression adds an expression as one column, under an alias. It binds nothing, because an expression is SQL.
func (*Builder) SelectRaw ¶
SelectRaw adds a raw expression to the select list, with its own bindings.
func (*Builder) SelectVectorDistance ¶
SelectVectorDistance adds the distance between a column's embedding and the vector given, as a column of the result.
as defaults to the column's name with _distance appended.
Accepting a string as the vector, and turning it into an embedding through a model provider, is not supported here, for the reason WhereVectorDistanceLessThan gives.
func (*Builder) SetAggregate ¶
SetAggregate sets the aggregate function and columns being compiled.
It also drops the ordering when there is no GROUP BY, which is easy to miss and is the half that matters: ORDER BY on an aggregate with no grouping is a sort of one row, and MySQL in strict mode refuses it outright when the ordering column is not in the select. The order bindings go with it, or the placeholders and the values stop lining up.
func (*Builder) SetBindings ¶
SetBindings replaces the bindings of the named segment.
func (*Builder) SharedLock ¶
SharedLock locks the selected rows with a shared lock.
func (*Builder) SimplePaginate ¶
func (b *Builder) SimplePaginate(ctx context.Context, g auth.Grant, perPage, page int, columns []any, opts pagination.Options) (*pagination.Paginator[Record], error)
SimplePaginate runs the query for one page without counting the total.
It reads one row more than the page holds, and that extra row is the whole of how it resolves "is there a next page" without a count. pagination.SimplePaginate drops it before anybody sees it.
func (*Builder) Sole ¶
Sole returns the query's only matching row, and errors if there is not exactly one.
It reads two rows to find out whether there is more than one, and reports ErrRecordsNotFound or ErrMultipleRecordsFound.
func (*Builder) SoleValue ¶
SoleValue returns the value of column from the query's only matching row, erroring as Sole does if there is not exactly one.
func (*Builder) StraightJoin ¶
StraightJoin is MySQL's join that forbids the planner from reordering the tables.
Every other engine is handed the type as written and rejects it, which is what the grammar's SupportsStraightJoins reports.
func (*Builder) StraightJoinSub ¶
StraightJoinSub is JoinSub with typ set to "straight_join".
func (*Builder) StraightJoinWhere ¶
StraightJoinWhere is JoinWhere with typ set to "straight_join".
func (*Builder) ToRawSQL ¶
ToRawSQL returns the statement with the bindings written into it, for reading rather than for running.
It carries an error because escaping a value needs a connection to escape through, and Grammar.Escape reports that rather than handing back a value that looks quoted and is not.
It takes the Grant because what it prints has to be what would run, tenant clause and all. A raw SQL dump that showed a query without its tenant filter would teach the reader that the filter is not there.
func (*Builder) ToSQL ¶
ToSQL runs the before-query callbacks and compiles the query to a select statement.
func (*Builder) Truncate ¶
Truncate empties the entire table, all tenants at once.
Read this before calling it. A truncate takes no where clause on any engine, so this is the one statement in the package that cannot carry the tenant: it empties the table for every customer in it, and the Grant it requires authorizes that rather than narrowing it. Deleting one tenant's rows is Delete, which is filtered.
It is more than one statement on some engines -- Postgres and SQL Server reset the sequence separately -- which is why the grammar returns a map of statements to bindings.
func (*Builder) Update ¶
Update updates the rows matching the query with the given column values.
A value may be a *Builder, which becomes the subquery it compiles to, with its bindings landing where its placeholders are. Such a subquery is scoped by the Grant first, for the reason InsertUsing's is.
A value under TenantColumn is replaced by the Grant's tenant rather than written: an update that moved a row to another tenant would pass its own where clause on the way out and be unreachable afterwards.
Two maps go to the grammar -- the values to compile and the bindings to send -- and both are keyed by column, so the grammar has to walk them in sorted key order for the placeholders and the values to line up.
func (*Builder) UpdateFrom ¶
func (b *Builder) UpdateFrom(ctx context.Context, g auth.Grant, values map[string]any) (int64, error)
UpdateFrom runs an "update ... from" statement, which only Postgres compiles.
func (*Builder) UpdateOrInsert ¶
func (b *Builder) UpdateOrInsert(ctx context.Context, g auth.Grant, attributes, values map[string]any) (bool, error)
UpdateOrInsert updates the first row matching attributes, or inserts one combining attributes and values if none matches.
attributes expands into one where clause per pair, added in sorted key order, so that two calls with the same attributes compile to the same statement.
values may be nil, which updates nothing and reports that the row is there.
func (*Builder) Upsert ¶
func (b *Builder) Upsert(ctx context.Context, g auth.Grant, values []map[string]any, uniqueBy []string, update []string) (int64, error)
Upsert inserts these rows, and updates the ones that collide on uniqueBy.
update names the columns an existing row takes from the new one. Nil means all of them; an empty non-nil slice means none, and turns the whole statement into a plain insert. Go's nil/empty-slice distinction is what keeps the two cases apart.
uniqueBy should name the tenant column too. The rows carry the tenant, but the conflict target is a unique index, and an index that does not include the tenant is a constraint shared between customers.
func (*Builder) UseWritePDO ¶
UseWritePDO sends the read to the write connection, for the case a replica has not caught up yet: a row inserted and read back in the same request is not there on a replica that is two hundred milliseconds behind.
The state behind it is unexported and read through UsingWritePDO, for the same reason From, Limit and Offset are: it is both a field and a fluent method, and Go holds both in one namespace.
func (*Builder) UsingWritePDO ¶
UsingWritePDO reports whether the read goes to the write connection. Mechanical, for the reason UseWritePDO gives.
func (*Builder) ValidateForCompilation ¶ added in v0.22.0
ValidateForCompilation applies the final barrier to the complete query graph without executing callbacks: every non-raw operator and every order direction has to be one the grammar declares. Grammar compilers use it to reject direct public-field mutations while leaving callback lifecycle ownership to Builder execution methods.
func (*Builder) ValidateForCompilationWith ¶ added in v0.22.0
ValidateForCompilationWith applies the same barrier under the operator policy of the grammar that is about to spell the SQL, which is not always the one the builder was given: a builder assembled for one dialect can be handed straight to another dialect's compiler, and the engine that receives the statement is the one that decides how each token reads.
The grammar the builder carries stays in the conversation, but only for word operators, which is how a grammar extending a dialect keeps the operators it adds. A nil compiler leaves the operators every dialect shares.
func (*Builder) Value ¶
Value returns the value of column from the query's first matching row.
A Record is a map and a map has no first, so the value is the only one when the row holds one, and otherwise the one under the column's own name -- with the table qualifier and the alias stripped, which is what the driver keys it by.
func (*Builder) When ¶
When runs the callback only if the condition holds, and hands the builder back either way.
The condition is a bool, because the caller writing the expression is the one who knows what makes it true. The callback mutates the builder and returns nothing: every method on Builder already mutates and returns the receiver, so a callback that returned something would be a second convention.
A nil callback on a true condition leaves the builder untouched instead of failing, which is what Collection.When does with the same argument.
q.From("posts").
When(published, func(q *query.Builder) { q.Where("published", true) }, nil).
OrderBy("id")
func (*Builder) Where ¶
Where adds a basic where clause, in either its two or three argument form.
Called with two arguments the operator is "=": where('id', 1) and where('id', '=', 1) are the same clause. Called with a func it opens a nested group instead.
func (*Builder) WhereAll ¶
WhereAll adds a clause requiring every one of the columns to compare with the same value, joined by "and" inside one group.
func (*Builder) WhereAny ¶
WhereAny adds a clause requiring any one of the columns to compare with the same value, joined by "or" inside one group.
func (*Builder) WhereBetween ¶
WhereBetween adds a clause requiring column to fall between from and to.
func (*Builder) WhereBetweenColumns ¶
WhereBetweenColumns adds a clause requiring column to be between two other columns, so nothing here is bound.
func (*Builder) WhereBindings ¶
WhereBindings rebuilds the where segment from the clauses, in the order the compiled statement consumes them.
It exists so that a clause carrying a subquery can be replaced -- which is what putting the tenant on a subquery does -- without the values afterwards sliding onto the wrong placeholders. Every clause type that contributes a binding is listed here, and a type that starts contributing one has to be added: a clause this does not know about loses its values silently, which is a wrong answer rather than an error.
func (*Builder) WhereColumn ¶
WhereColumn adds a clause comparing two columns.
func (*Builder) WhereDate ¶
WhereDate adds a clause comparing the date part of a timestamp column with a date.
The operator is optional, as it is on Where: two arguments are a column and a value compared with "=". A time.Time value is formatted down to the day.
func (*Builder) WhereExists ¶
WhereExists adds an exists clause for the subquery the callback builds.
func (*Builder) WhereFullText ¶
func (b *Builder) WhereFullText(columns []any, value any, options map[string]any, boolean string) *Builder
WhereFullText adds a full-text search clause over the given columns.
options carries the engine's search modes -- MySQL reads "mode" and "expanded", Postgres reads "language" -- and a grammar that has none ignores it.
func (*Builder) WhereIn ¶
WhereIn adds a where-in clause.
An empty list is kept rather than dropped: it compiles to "0 = 1", so a filter over an empty set returns nothing. Dropping it would return everything, which is the difference between an empty page and a data leak.
func (*Builder) WhereIntegerInRaw ¶
WhereIntegerInRaw adds a where-in clause whose values are written directly into the statement as integers rather than bound.
Every value is cast to an integer first: an integer has no quoting to escape. A value that is not a number at all becomes zero rather than reaching the statement as itself.
func (*Builder) WhereIntegerNotInRaw ¶
WhereIntegerNotInRaw adds a where-not-in clause with raw integer values.
func (*Builder) WhereJSONContains ¶
WhereJSONContains adds a clause requiring the JSON column to contain value.
func (*Builder) WhereJSONContainsKey ¶
WhereJSONContainsKey adds a clause requiring the JSON column to contain the given key path. The key is part of the path, so there is nothing to bind.
func (*Builder) WhereJSONDoesntContain ¶
WhereJSONDoesntContain adds a clause requiring the JSON column not to contain value.
func (*Builder) WhereJSONDoesntContainKey ¶
WhereJSONDoesntContainKey adds a clause requiring the JSON column not to contain the given key path.
func (*Builder) WhereJSONDoesntOverlap ¶
WhereJSONDoesntOverlap adds a clause requiring the JSON column not to overlap value.
func (*Builder) WhereJSONLength ¶
WhereJSONLength adds a clause comparing the length of a JSON column. The bound value is an integer: it is compared with a length.
func (*Builder) WhereJSONOverlaps ¶
WhereJSONOverlaps adds a clause requiring the JSON column to overlap value.
func (*Builder) WhereLike ¶
func (b *Builder) WhereLike(column any, value any, caseSensitive bool, boolean string, not bool) *Builder
WhereLike adds a LIKE clause comparing column against a pattern, optionally case sensitive.
The clause carries the value that is bound rather than the pattern that was written, because a grammar may rewrite it -- SQLite spells a case sensitive like as a glob, whose wildcards are the other way round -- and the tenant scoping rebuilds the binding list from the clauses. A clause that did not carry its own value would lose it there.
func (*Builder) WhereMonth ¶
WhereMonth adds a clause comparing the month part of a timestamp column.
func (*Builder) WhereNested ¶
WhereNested opens a nested group of clauses, built by the callback, and adds it under boolean.
func (*Builder) WhereNone ¶
WhereNone adds a clause requiring none of the columns to compare with the same value: WhereAny negated, with the group joined by "and not".
func (*Builder) WhereNotBetween ¶
WhereNotBetween adds a not-between clause.
func (*Builder) WhereNotBetweenColumns ¶
WhereNotBetweenColumns adds a not-between-columns clause.
func (*Builder) WhereNotIn ¶
WhereNotIn adds a where-not-in clause.
func (*Builder) WhereNotLike ¶
WhereNotLike adds a NOT LIKE clause.
func (*Builder) WhereNotNull ¶
WhereNotNull adds a clause requiring the named columns not to be NULL.
func (*Builder) WhereRaw ¶
WhereRaw adds a raw SQL where clause, with its own bindings.
The bindings are recorded on the clause as well as appended to the segment, because the tenant filter needs to rebuild the flat list -- scoping a subquery changes how many bindings it contributes, and the list can only be put back in order if every clause knows which of them are its own.
func (*Builder) WhereRowValues ¶
func (b *Builder) WhereRowValues(columns []any, operator string, values []any, boolean string) *Builder
WhereRowValues adds a clause comparing a tuple of columns with a tuple of values.
func (*Builder) WhereSubCount ¶
WhereSubCount adds a where clause with a subquery on the LEFT of a comparison: a subquery like `(select count(*) from posts where posts.user_id = users.id) > 3`.
The builder had no method for that shape, so both copies of the model has-query wrote the clause by hand, as a Basic where whose column was Raw("(" + sub.ToSQL() + ")"). A subquery frozen into a Raw is a subquery nothing can scope afterwards, and this one was never scoped by anything: Users.Has("posts", ">", 3).Get(auth.SystemGrant("user.list", "acme")) emitted `(select count(*) from "posts" where "users"."id" = "posts"."user_id") > 3`, with no posts.tenant_id anywhere in it, so one tenant's users were filtered by every tenant's posts.
The clause keeps the builder it was compiled from, which is why it can be scoped: scopeSubqueries scopes that builder under the Grant and renders the column again from it. The SQL written here is what an unscoped ToSQL shows, exactly as it is for every other subquery in this file.
func (*Builder) WhereTime ¶
WhereTime adds a clause comparing the time part of a timestamp column with a time.
func (*Builder) WhereValueBetween ¶
WhereValueBetween adds a clause requiring value to fall between two columns, which is the between comparison the other way round.
func (*Builder) WhereValueNotBetween ¶
WhereValueNotBetween adds a value-not-between-columns clause.
func (*Builder) WhereVectorDistanceLessThan ¶
func (b *Builder) WhereVectorDistanceLessThan(column any, vector []float64, maxDistance float64, boolean string) *Builder
WhereVectorDistanceLessThan adds a clause matching rows whose embedding is nearer than maxDistance to the given vector.
It takes the vector directly rather than accepting text and computing an embedding from it, because a query builder that makes a network call to an embedding provider is a query builder that can time out. The caller fetches the embedding and passes it in.
Nothing here checks that the connection is Postgres: the operator is Postgres's, and a fluent method has nothing to report an error through, so an unsupported connection fails when the engine refuses the SQL rather than before.
type Connection ¶
type Connection interface {
// Select runs a select and returns its rows.
Select(ctx context.Context, query string, bindings []any, useReadPDO bool) ([]Record, error)
// Insert runs an insert.
Insert(ctx context.Context, query string, bindings []any) (bool, error)
// Update runs an update and returns the number of rows affected.
Update(ctx context.Context, query string, bindings []any) (int64, error)
// Delete runs a delete and returns the number of rows affected.
Delete(ctx context.Context, query string, bindings []any) (int64, error)
// Statement runs a statement that returns neither rows nor a count.
Statement(ctx context.Context, query string, bindings []any) (bool, error)
}
Connection is what a query builder asks of the thing that runs its statements.
It is declared here rather than imported from the database package because the interface belongs with its consumer in Go, and because database imports this package: naming it there would close the cycle. Every method takes a context, and it is the request's -- not one the connection was built with. A statement that cannot be cancelled outlives the request that asked for it, and a deadline that stops at the handler is a deadline the database never hears about.
type CursorConnection ¶
type CursorConnection interface {
// Cursor runs a select and yields its rows one at a time.
Cursor(ctx context.Context, query string, bindings []any, useReadPDO bool) (func(yield func(Record, error) bool), error)
}
CursorConnection is the part of a connection that Cursor needs: a select that yields its rows one at a time instead of materialising them.
A connection that does not implement it makes Cursor fail rather than fall back to a buffered select. The fallback would work and would be a lie: the whole reason to reach for a cursor is the result set that does not fit in memory, and finding out by being killed is worse than finding out by an error.
type Expression ¶
type Expression struct {
// contains filtered or unexported fields
}
Expression is a value the grammar must not wrap in identifier quotes and must not turn into a placeholder.
Everything the query builder accepts as a column or a value also accepts an Expression.
func (Expression) GetValue ¶
func (e Expression) GetValue(grammar Grammar) any
GetValue returns the wrapped value. The grammar parameter is accepted and ignored: the value carried here is already final, and the parameter exists only so Expression satisfies the same signature as a grammar-aware value.
func (Expression) String ¶
func (e Expression) String() string
String renders the expression the way the grammar concatenates it.
func (Expression) Value ¶
func (e Expression) Value() any
Value returns the wrapped value without requiring a grammar argument, for callers that have no grammar handy and do not need one.
type Grammar ¶
type Grammar interface {
// CompileSelect compiles a select statement for the query.
CompileSelect(query *Builder) string
// CompileInsert compiles an insert statement for the given rows.
CompileInsert(query *Builder, values []map[string]any) string
// CompileInsertOrIgnore compiles an insert that silently skips rows that
// would violate a constraint.
CompileInsertOrIgnore(query *Builder, values []map[string]any) string
// CompileInsertGetID compiles an insert and reports the SQL that reads
// back the inserted row's ID from the given sequence.
CompileInsertGetID(query *Builder, values map[string]any, sequence string) string
// CompileUpdate compiles an update statement for the given values.
CompileUpdate(query *Builder, values map[string]any) string
// CompileUpsert compiles an insert that updates the named columns when a
// row conflicts on uniqueBy.
CompileUpsert(query *Builder, values []map[string]any, uniqueBy []string, update []string) string
// CompileDelete compiles a delete statement for the query.
CompileDelete(query *Builder) string
// CompileTruncate compiles a truncate. A truncate is more than one
// statement on some engines, so the result is a map from each statement
// to its bindings.
CompileTruncate(query *Builder) map[string][]any
// CompileExists compiles a select wrapped so the engine can report only
// whether a row matches.
CompileExists(query *Builder) string
// CompileRandom compiles a random ordering expression, optionally seeded.
CompileRandom(seed string) string
// PrepareBindingsForUpdate arranges the where bindings after the update
// values, in the order the compiled statement consumes them.
PrepareBindingsForUpdate(bindings map[string][]any, values map[string]any) []any
// PrepareBindingsForDelete returns the where bindings for a delete
// statement.
PrepareBindingsForDelete(bindings map[string][]any) []any
// SupportsSavepoints reports whether the engine can savepoint within a
// transaction.
SupportsSavepoints() bool
// CompileSavepoint compiles a statement that creates the named savepoint.
CompileSavepoint(name string) string
// CompileSavepointRollBack compiles a statement that rolls back to the
// named savepoint.
CompileSavepointRollBack(name string) string
// GetOperators returns the comparison operators the grammar accepts.
GetOperators() []string
// GetBitwiseOperators returns the operators treated as bitwise rather
// than comparison.
GetBitwiseOperators() []string
// Wrap quotes an identifier, leaving an Expression alone.
Wrap(value any) string
// WrapTable quotes a table name, applying the table prefix and any alias.
WrapTable(table any) string
// WrapArray quotes each value in a list of identifiers.
WrapArray(values []any) []string
// Columnize quotes a list of columns and joins them with commas.
Columnize(columns []any) string
// Parameterize returns the comma-separated placeholders for a list of
// values.
Parameterize(values []any) string
// Parameter returns the placeholder for a value, or the value itself when
// it is an Expression.
Parameter(value any) string
// QuoteString quotes a string literal, or each one in a list.
QuoteString(value any) string
// Escape returns a value escaped for inclusion directly in SQL, for a
// caller building a statement by hand rather than through a placeholder.
//
// It returns an error rather than panicking: a grammar with no connection
// cannot escape safely, and returning the unescaped value in that case
// would be an injection with a reassuring name.
Escape(value any, binary bool) (string, error)
// GetDateFormat returns the layout the engine's date columns are
// formatted with, in Go's reference-time syntax.
GetDateFormat() string
// GetTablePrefix returns the prefix applied to every table name.
GetTablePrefix() string
// SetTablePrefix sets the prefix applied to every table name.
SetTablePrefix(prefix string) Grammar
}
Grammar is what a Builder needs of the thing that spells its SQL.
It is an interface, declared in the package that consumes it, because the concrete grammars live in query/grammars and naming them here would close an import cycle: grammars imports query for *Builder, so query cannot import grammars for the type.
A driver grammar embeds BaseGrammar and overrides what its dialect spells differently.
type GroupLimit ¶
GroupLimit is the per-group row limit a Builder was given.
type Having ¶
type Having struct {
Type string
Column any
Operator string
Value any
Values []any
Boolean string
Not bool
SQL string
Query *Builder
}
Having is one having clause of a Builder.
type IndexHint ¶
IndexHint is the index a query asks the planner to use, force or ignore: what Builder.UseIndex, ForceIndex and IgnoreIndex record, and what the grammar compiles into the from clause.
Type is one of "hint", "force" and "ignore", and Index is the index name. A builder holds at most one, so setting a second replaces the first.
A hint changes the plan and never the rows, which is why a grammar is free to compile it to nothing: the base Grammar does, SQLite honours only "force", and an index name that is not a bare identifier is dropped rather than interpolated, because an identifier cannot be bound.
func NewIndexHint ¶
NewIndexHint builds an IndexHint of the given type and index name.
type InsertOrIgnoreReturningGrammar ¶
type InsertOrIgnoreReturningGrammar interface {
// CompileInsertOrIgnoreReturning compiles an insert that skips colliding
// rows and returns the ones it wrote.
CompileInsertOrIgnoreReturning(query *Builder, values []map[string]any, uniqueBy, returning []string) (string, error)
}
InsertOrIgnoreReturningGrammar is the part of a grammar that compiles an insert which skips the rows that would collide and reports the ones it wrote. It is asked for rather than declared on Grammar, for the reason InsertUsingGrammar is.
type InsertUsingGrammar ¶
type InsertUsingGrammar interface {
// CompileInsertUsing compiles an insert that reads its rows from a select
// query.
CompileInsertUsing(query *Builder, columns []any, sql string) string
// CompileInsertOrIgnoreUsing compiles CompileInsertUsing's insert-or-ignore
// variant.
CompileInsertOrIgnoreUsing(query *Builder, columns []any, sql string) string
}
InsertUsingGrammar is the part of a grammar that compiles an insert reading from a select. It is asked for rather than declared on Grammar because the Grammar interface is closed and this is not on it.
type InvalidDirectionError ¶ added in v0.22.0
type InvalidDirectionError struct {
Direction string
}
InvalidDirectionError identifies the order direction a query refused.
Use errors.Is with ErrInvalidDirection when the concrete value is not needed.
func (*InvalidDirectionError) Error ¶ added in v0.22.0
func (e *InvalidDirectionError) Error() string
Error returns a deterministic description of the refused direction.
func (*InvalidDirectionError) Unwrap ¶ added in v0.22.0
func (e *InvalidDirectionError) Unwrap() error
Unwrap makes InvalidDirectionError match ErrInvalidDirection with errors.Is.
type InvalidOperatorError ¶ added in v0.22.0
type InvalidOperatorError struct {
Operator string
}
InvalidOperatorError identifies the operator a query refused.
Use errors.Is with ErrInvalidOperator when the concrete value is not needed.
func (*InvalidOperatorError) Error ¶ added in v0.22.0
func (e *InvalidOperatorError) Error() string
Error returns a deterministic description of the refused operator.
func (*InvalidOperatorError) Unwrap ¶ added in v0.22.0
func (e *InvalidOperatorError) Unwrap() error
Unwrap makes InvalidOperatorError match ErrInvalidOperator with errors.Is.
type JSONContainsGrammar ¶
type JSONContainsGrammar interface {
// PrepareBindingForJSONContains turns a value into the JSON binding the
// grammar's engine expects.
PrepareBindingForJSONContains(binding any) (any, error)
}
JSONContainsGrammar is the part of a grammar that turns a value into the JSON binding its engine expects. It is asked for rather than declared on Grammar, for the reason InsertUsingGrammar is.
type JoinClause ¶
type JoinClause struct {
*Builder
// Type is the join type: inner, left, right or cross.
Type string
// Table is the table or subquery expression being joined.
Table any
// Lateral marks the join as lateral. It is a flag rather than a second
// type, so the grammar and Joins have one type to hold.
Lateral bool
// contains filtered or unexported fields
}
JoinClause is one join, and the condition it is joined on.
It embeds *Builder, so a join condition is written with the same where vocabulary as the query itself -- On is where for two columns, and Where inside a join is a where. Every Builder method is reachable on a JoinClause, and the two that behave differently are declared below and shadow the embedded ones.
func NewJoinClause ¶
func NewJoinClause(parentQuery *Builder, typ string, table any) *JoinClause
NewJoinClause builds a JoinClause for a join against table.
The clause carries the parent's connection, grammar and processor so that a nested query built inside the join compiles against the same dialect.
func NewJoinLateralClause ¶
func NewJoinLateralClause(parentQuery *Builder, typ string, table any) *JoinClause
NewJoinLateralClause builds a JoinClause with Lateral already set. See Lateral.
func (*JoinClause) NewJoinClause ¶
func (j *JoinClause) NewJoinClause() *JoinClause
NewJoinClause returns another JoinClause rather than a Builder.
Go resolves an embedded method by name, and a method on JoinClause called NewQuery could not return *JoinClause while the embedded one returns *Builder, so the two are separate names: NewQuery still returns a plain builder, for a subquery inside the join, and this returns the clause.
func (*JoinClause) NewParentQuery ¶
func (j *JoinClause) NewParentQuery() *Builder
NewParentQuery returns a fresh builder on the table the join was declared against.
func (*JoinClause) On ¶
func (j *JoinClause) On(first any, args ...any) *JoinClause
On adds a join condition.
It compares two columns, so neither side becomes a binding: `on('users.id', '=', 'posts.user_id')` names a column on the right, not the string "posts.user_id". This is the one difference that catches people moving a condition from where to on -- in a where, the right side is a value.
Passing a func opens a nested group.
func (*JoinClause) OrOn ¶
func (j *JoinClause) OrOn(first any, args ...any) *JoinClause
OrOn is On joined with "or" instead of "and".
type LikeBindingGrammar ¶
type LikeBindingGrammar interface {
// PrepareWhereLikeBinding rewrites a like pattern into the binding the
// grammar's engine expects.
PrepareWhereLikeBinding(value string, caseSensitive bool) string
}
LikeBindingGrammar is the part of a grammar that rewrites a like pattern for the engine. A grammar that does not implement it leaves the pattern alone.
type PreparesBindings ¶
type PreparesBindings interface {
// PrepareBindings turns a driver-specific value into one the driver
// accepts.
PrepareBindings(bindings []any) []any
}
PreparesBindings turns a driver-specific value into one the driver accepts. ToRawSQL asks for it, and takes the bindings unchanged from a connection that has no opinion.
type Processor ¶
type Processor interface {
// ProcessSelect adjusts the rows a select returned before they reach the
// caller.
ProcessSelect(query *Builder, results []Record) []Record
// ProcessInsertGetID runs an insert and reports the ID of the inserted
// row, read back from the named sequence.
ProcessInsertGetID(ctx context.Context, query *Builder, sql string, values []any, sequence string) (int64, error)
}
Processor is the hook that lets a driver adjust results on the way out.
type UpdateFromGrammar ¶
type UpdateFromGrammar interface {
// CompileUpdateFrom compiles an "update ... from" statement.
CompileUpdateFrom(query *Builder, values map[string]any) string
// PrepareBindingsForUpdateFrom orders the bindings for an "update ... from"
// statement to match the placeholders CompileUpdateFrom produces.
PrepareBindingsForUpdateFrom(bindings map[string][]any, values map[string]any) []any
}
UpdateFromGrammar is the part of the grammar that compiles Postgres's "update ... from" syntax.
Not every grammar implements it, so callers use a type assertion against this interface and return an error when it fails, rather than calling a method that might not exist.
type Where ¶
type Where struct {
Type string
Column any
Columns []any
First any
Second any
Operator string
Value any
Values []any
Boolean string
Not bool
SQL any
Query *Builder
CaseSensitive bool
Options map[string]any
}
Where is one where clause of a Builder.
Each Type reads a different subset of the fields; the union of them is spelled out here so the grammar can read them.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package grammars holds one grammar per engine, each one compiling a *query.Builder into the SQL that engine speaks: MySQLGrammar, MariaDBGrammar, PostgresGrammar and SQLiteGrammar, over the shared Grammar in grammar.go.
|
Package grammars holds one grammar per engine, each one compiling a *query.Builder into the SQL that engine speaks: MySQLGrammar, MariaDBGrammar, PostgresGrammar and SQLiteGrammar, over the shared Grammar in grammar.go. |
|
Package processors holds the hook a driver takes to adjust results on the way out of the connection: MySQLProcessor, MariaDBProcessor, PostgresProcessor and SQLiteProcessor over the shared Processor.
|
Package processors holds the hook a driver takes to adjust results on the way out of the connection: MySQLProcessor, MariaDBProcessor, PostgresProcessor and SQLiteProcessor over the shared Processor. |