Documentation
¶
Overview ¶
Package builder builds typed SQL fragments for tables, statements, and clauses.
Fragments implement frag.Fragment and can be collected into query text and args. See Example* tests in this package for end-to-end renderings.
Definitions ¶
- Col / C / CT / CC: a column. C creates by name; CT/CC add a Go type for typed conditions and assignments. ColumnsOf / Columns / ColsOf group columns.
- Key / PK / UK / K: primary key and indexes on a table.
- Table / T: a table with columns and keys. T builds from definitions; TFrom scans a Model (struct with db tags and optional PrimaryKey / Indexes / UniqueIndexes methods) into a Table.
- TFrom: scan a go type (struct pointer) to Table
- Catalog / NewCatalog: a named registry of tables (Add / T / Tables).
- Model: table-backed struct type used with TFrom and generated models.
Example table setup (from ExampleJoin):
tUser := T(
"t_user",
C("f_id", WithColDefOf(uint64(0), `,autoinc`)),
C("f_name", WithColDefOf("", `,width=128,default=''`)),
C("f_org_id", WithColDefOf(uint64(0), ``)),
)
Statements ¶
Select: SELECT ... FROM table with additions (modifiers like SQL_CALC_FOUND_ROWS, DISTINCT ON, FOR UPDATE / FOR SHARE).
Insert: INSERT [IGNORE] INTO ... VALUES / SELECT, with OnConflict / OnDuplicate.
Update / UpdateIgnore: UPDATE ... SET ... [FROM|JOIN] WHERE, optional Returning.
Delete: DELETE FROM ... WHERE.
With / WithRecursive: CTE / WITH statements.
Select(nil).From(tUser, Where(CT[int]("F_id").AsCond(Eq(1))), Limit(10)) // SELECT * FROM t_user WHERE f_id = ? LIMIT 10
Insert().Into(T("t_user")).Values(Columns("f_a", "f_b"), 1, 2) // INSERT INTO t_user (f_a,f_b) VALUES (?,?)
Delete().From(T("t_x"), Where(CT[int]("F_a").AsCond(Eq(1)))) // DELETE FROM t_x WHERE f_a = ?
Update(t).Set(...).Where(..., Returning(nil)) // UPDATE ... SET ... WHERE ... RETURNING *
Additions (clauses) ¶
Attach to From / Into / Where via Additions. Types sort automatically when rendered.
Comment: leading SQL comments (-- ...)
Where: WHERE condition
Join / LeftJoin / RightJoin / FullJoin / InnerJoin / CrossJoin: JOIN ... ON / USING
GroupBy: GROUP BY ... [HAVING ...]
OrderBy / Order / AscOrder / DescOrder: ORDER BY (NullsFirst / NullsLast)
Limit: LIMIT n [.Offset(m)]; negative count omits LIMIT
OnConflict: INSERT ... ON CONFLICT (...) DO NOTHING / DO UPDATE SET
OnDuplicate: INSERT ... ON DUPLICATE KEY UPDATE (MySQL)
Returning: RETURNING ...
ForUpdate / ForUpdateSkipLocked / ForUpdateNoWait: FOR UPDATE
ForShare / ForShareSkipLocked / ForShareNoWait: FOR SHARE
e.g.
Select(nil).
From(
T("t_x"),
Where(CT[int]("F_a").AsCond(Eq(1))),
GroupBy(C("F_a")).Having(CT[int]("F_a").AsCond(Eq(1))),
Limit(20).Offset(100),
Comment("limit with offset"),
)
Insert().Into(
T("t_user"),
OnConflict(ColsOf(C("f_id"))).DoNothing(),
).Values(ColsOf(C("f_id"), C("f_name")), 1, "saito")
Conditions ¶
Build predicates with typed column helpers, then compose:
Col.AsCond with Eq / Neq / Lt / Gt / Gte / In / Like / LLike / RLike / EqCol / ...
AsCond: wrap any fragment as a condition
Exists: EXISTS (subquery)
e.g.:
Xor(
Or(
And(
CT[int]("a").AsCond(Lt(1)),
CT[string]("b").AsCond(LLike[string]("text")),
),
CT[int]("a").AsCond(Eq(2)),
),
CT[string]("b").AsCond(RLike[string]("g")),
)
// (((a < ?) AND (b LIKE ?)) OR (a = ?)) XOR (b LIKE ?)
Functions ¶
Aggregate and misc SQL functions via Func helpers:
Count: COUNT(1) when empty, else COUNT(args); Func("COUNT") → COUNT(*)
AnyValue / First / Last / Distinct
Count() // COUNT(1) Count(C("a")) // COUNT(a) Avg(C("a")) // AVG(a)
Assignments ¶
ColumnsAndValues and typed AssignBy / Value / AsValue / Inc build SET and INSERT value lists (see ExampleAssignment, ExampleUpdate, ExampleInsert).
Index ¶
- Variables
- func Alias(f frag.Fragment, name string) frag.Fragment
- func AutoAlias(columns ...frag.Fragment) frag.Fragment
- func ContextWithToggles(ctx context.Context, ts Toggles) context.Context
- func DistinctOn(on ...frag.Fragment) frag.Fragment
- func GetColComputed(c Col) frag.Fragment
- func HasToggle(ctx context.Context, toggle ToggleType) bool
- func KeyColumnsDefOf(k Key) frag.Fragment
- func NullsFirst() frag.Fragment
- func NullsLast() frag.Fragment
- func TableNames(c Catalog) iter.Seq[string]
- func TrimToggles(ctx context.Context, toggles ...ToggleType) context.Context
- func WithToggles(ctx context.Context, toggles ...ToggleType) context.Context
- type Addition
- func AsAddition(t AdditionType, f frag.Fragment) Addition
- func Comment(lines ...string) Addition
- func ForShare(modifiers ...string) Addition
- func ForShareNoWait() Addition
- func ForShareSkipLocked() Addition
- func ForUpdate(modifiers ...string) Addition
- func ForUpdateNoWait() Addition
- func ForUpdateSkipLocked() Addition
- func OnDuplicate(assignments ...Assignment) Addition
- func OrderBy(os ...OrderAddition) Addition
- func Where(f frag.Fragment) Addition
- type AdditionType
- type Additions
- type Assignment
- type AssignmentMarker
- type Assignments
- type Catalog
- type Col
- type ColComputed
- type ColDef
- type ColIter
- type ColModifier
- type ColOption
- type ColPick
- type ColValuer
- func AsValue[T any](v TCol[T]) ColValuer[T]
- func Between[T comparable](min, max T) ColValuer[T]
- func Dec[T any](v T) ColValuer[T]
- func Eq[T comparable](v T) ColValuer[T]
- func EqCol[T comparable](v TCol[T]) ColValuer[T]
- func Gt[T comparable](v T) ColValuer[T]
- func Gte[T comparable](v T) ColValuer[T]
- func In[T any](vs ...T) ColValuer[T]
- func Inc[T any](v T) ColValuer[T]
- func IsNotNull[T any]() ColValuer[T]
- func IsNull[T any]() ColValuer[T]
- func LLike[T ~string](s T) ColValuer[T]deprecated
- func Like[T ~string](s T) ColValuer[T]
- func Lt[T comparable](v T) ColValuer[T]
- func Lte[T comparable](v T) ColValuer[T]
- func Match[T ~string](s T) ColValuer[T]
- func MatchPrefix[T ~string](s T) ColValuer[T]
- func MatchSuffix[T ~string](s T) ColValuer[T]
- func Neq[T comparable](v T) ColValuer[T]
- func NeqCol[T comparable](v TCol[T]) ColValuer[T]
- func NotBetween[T comparable](min, max T) ColValuer[T]
- func NotIn[T any](vs ...T) ColValuer[T]
- func NotLike[T ~string](s T) ColValuer[T]
- func RLike[T ~string](s T) ColValuer[T]deprecated
- func Value[T any](v T) ColValuer[T]
- type ColWrapper
- type Cols
- type ColsManager
- type ColumnDef
- type CombinationAddition
- type ComposedCondition
- type Condition
- type ConditionMarker
- type Function
- func AnyValue(fragments ...frag.Fragment) *Function
- func Avg(fragments ...frag.Fragment) *Function
- func Count(fragments ...frag.Fragment) *Function
- func Distinct(fragments ...frag.Fragment) *Function
- func First(fragments ...frag.Fragment) *Function
- func Func(name string, args ...frag.Fragment) *Function
- func Last(fragments ...frag.Fragment) *Function
- func Max(fragments ...frag.Fragment) *Function
- func Min(fragments ...frag.Fragment) *Function
- func Sum(fragments ...frag.Fragment) *Function
- type GroupByAddition
- type HasSchema
- type HasTableName
- type JoinAddition
- type Key
- type KeyColumnOption
- type KeyDef
- type KeyDefine
- type KeyIter
- type KeyKind
- type KeyOption
- type KeyPick
- type Keys
- type KeysManager
- type LimitAddition
- type Model
- type Newer
- type OnConflictAddition
- type OrderAddition
- type ReturningAddition
- type SelectStatement
- type SqlCondition
- type StmtDelete
- type StmtInsert
- type StmtSelect
- type StmtUpdate
- func (s *StmtUpdate) Frag(ctx context.Context) frag.Iter
- func (s StmtUpdate) From(from Table, additions ...Addition) *StmtUpdate
- func (s *StmtUpdate) IsNil() bool
- func (s StmtUpdate) Set(assignments ...Assignment) *StmtUpdate
- func (s StmtUpdate) Where(cond frag.Fragment, additions ...Addition) *StmtUpdate
- type SubQuery
- type TCol
- type Table
- type ToggleType
- type Toggles
- type WithColumnComment
- type WithColumnDesc
- type WithColumnRel
- type WithDatatypeDesc
- type WithIndexes
- type WithPrimaryKey
- type WithSchema
- type WithStmt
- type WithTable
- type WithTableDesc
- type WithTableName
- type WithUniqueIndexes
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrUpdateNeedLimitation = any(nil)
ErrUpdateNeedLimitation is reserved for update-without-limit errors.
Functions ¶
func ContextWithToggles ¶
ContextWithToggles merges ts into the context toggles.
func DistinctOn ¶
DistinctOn mysql/sqlite unsupported Alternative:
SELECT `_id`, `score` FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY `_id` ORDER BY `score` ASE) AS `row_no` FROM `table`
) AS grouped WHERE `row_no` = 1
func GetColComputed ¶
GetColComputed returns the computed expression of c, unwrapping ColWrapper if needed.
func HasToggle ¶
func HasToggle(ctx context.Context, toggle ToggleType) bool
HasToggle reports whether toggle is enabled in ctx.
func KeyColumnsDefOf ¶
KeyColumnsDefOf renders key column definitions for DDL.
func NullsFirst ¶
NullsFirst mysql/sqlite unsupported Alternative: ORDER BY `col` IS NULL
func TableNames ¶
TableNames iterates table names in a catalog.
func TrimToggles ¶
func TrimToggles(ctx context.Context, toggles ...ToggleType) context.Context
TrimToggles disables the given toggles on ctx.
func WithToggles ¶
func WithToggles(ctx context.Context, toggles ...ToggleType) context.Context
WithToggles enables the given toggles on ctx.
Types ¶
type Addition ¶
type Addition interface {
frag.Fragment
Type() AdditionType
}
Addition is a SQL clause attached to a statement (WHERE, JOIN, ...).
func AsAddition ¶
func AsAddition(t AdditionType, f frag.Fragment) Addition
AsAddition wraps f as an Addition of type t.
func ForShareNoWait ¶ added in v0.1.24
func ForShareNoWait() Addition
ForShareNoWait builds FOR SHARE NOWAIT.
func ForShareSkipLocked ¶ added in v0.1.24
func ForShareSkipLocked() Addition
ForShareSkipLocked builds FOR SHARE SKIP LOCKED.
func ForUpdateNoWait ¶ added in v0.1.24
func ForUpdateNoWait() Addition
ForUpdateNoWait builds FOR UPDATE NOWAIT.
func ForUpdateSkipLocked ¶ added in v0.1.24
func ForUpdateSkipLocked() Addition
ForUpdateSkipLocked builds FOR UPDATE SKIP LOCKED.
func OnDuplicate ¶
func OnDuplicate(assignments ...Assignment) Addition
OnDuplicate builds an ON DUPLICATE KEY UPDATE addition.
func OrderBy ¶
func OrderBy(os ...OrderAddition) Addition
OrderBy builds an ORDER BY addition.
Example ¶
f := Select(nil).
From(
T("t_x"),
OrderBy(
AscOrder(C("F_a")),
DescOrder(C("F_b")),
),
Where(
And(
CT[int]("F_a").AsCond(Eq(1)),
CT[int]("F_b").Fragment("# = ?+1", CT[int]("F_a")),
),
),
Comment("orders addition"),
)
Print(context.Background(), f)
f = Select(nil).
From(
T("t_y"),
AscOrder(C("F_id")),
DescOrder(C("F_name")),
Comment("order additions"),
)
Print(context.Background(), f)
Output: -- orders addition SELECT * FROM t_x WHERE (f_a = ?) AND (f_b = f_a+1) ORDER BY (f_a) ASC,(f_b) DESC [1] -- order additions SELECT * FROM t_y (f_id) ASC (f_name) DESC []
type Additions ¶
type Additions []Addition
Additions is an ordered collection of Addition clauses.
func ExtractAdditions ¶
func ExtractAdditions(t AdditionType, additions ...Addition) (filtered Additions)
ExtractAdditions returns additions matching type t.
type Assignment ¶
type Assignment interface {
frag.Fragment
AssignmentMarker
}
Assignment is a SET/VALUES assignment fragment.
Example ¶
f := ColumnsAndValues(Columns("a", "b"), 1, 2, 3, 4, 5, 6)
Print(WithToggles(context.Background(), TOGGLE__TUPLE_ASSIGNMENTS), f)
f = ColumnsAndValues(Columns("a", "b"), 1, 2)
Print(context.Background(), f)
Output: (a,b) VALUES (?,?), (?,?), (?,?) [1 2 3 4 5 6] a = ?, b = ? [1 2]
func ColumnsAndValues ¶
func ColumnsAndValues(cols frag.Fragment, values ...any) Assignment
ColumnsAndValues returns Assigment cols should be a Col or Cols
type AssignmentMarker ¶
type AssignmentMarker interface {
// contains filtered or unexported methods
}
AssignmentMarker marks assignment fragments.
type Assignments ¶
type Assignments []Assignment
Assignments is a list of Assignment values.
func (Assignments) IsNil ¶
func (as Assignments) IsNil() bool
type Catalog ¶
type Catalog interface {
// T picks a table by name.
T(string) Table
// Tables iterates registered tables.
Tables() iter.Seq[Table]
// Add registers tables into the catalog.
Add(...Table)
// Remove unregisters a table by name.
Remove(string)
// Len returns the number of tables.
Len() int
}
Catalog is a registry of tables.
func CatalogFrom ¶
CatalogFrom builds a Catalog from model instances.
type Col ¶
type Col interface {
frag.Fragment
// Name returns the database column name.
Name() string
// FieldName returns the struct field name of the column definition.
FieldName() string
// String returns the qualified name like `table.column`.
String() string
// Of rebinds the column to the given table context.
Of(Table) Col
// Fragment builds a SQL fragment with `#` as a placeholder for this column.
Fragment(q string, args ...any) frag.Fragment
}
Col a database column.
type ColComputed ¶
ColComputed exposes a computed expression for a column.
type ColDef ¶
type ColDef interface {
// Def returns the column definition.
Def() ColumnDef
}
ColDef exposes column definition metadata.
type ColModifier ¶
ColModifier mutates column construction options.
type ColOption ¶
type ColOption func(ColModifier)
ColOption configures a column at construction time.
func WithColComputed ¶
WithColComputed sets a computed expression for a column.
func WithColDefOf ¶
WithColDefOf parses a ColumnDef from a sample value and struct tag.
func WithColFieldName ¶
WithColFieldName sets the struct field name of a column.
type ColPick ¶
type ColPick interface {
// C picks a column by column name or field name.
C(string) Col
// Pick returns a column subset by names.
Pick(...string) Cols
}
ColPick picks columns by name.
type ColValuer ¶
ColValuer builds a typed expression against a column.
func Between ¶
func Between[T comparable](min, max T) ColValuer[T]
Between builds `column BETWEEN min AND max`.
func MatchPrefix ¶ added in v0.2.7
MatchPrefix builds `column LIKE s%`.
func MatchSuffix ¶ added in v0.2.7
MatchSuffix builds `column LIKE %s`.
func NotBetween ¶
func NotBetween[T comparable](min, max T) ColValuer[T]
NotBetween builds `column NOT BETWEEN min AND max`.
type ColWrapper ¶
type ColWrapper interface {
Unwrap() Col
}
ColWrapper unwraps a wrapped column to its underlying Col.
type Cols ¶
type Cols interface {
ColPick
ColIter
// Of rebinds all columns to the given table context.
Of(Table) Cols
// Len returns the number of columns.
Len() int
frag.Fragment
}
Cols is a set of columns.
func ColsIterOf ¶
ColsIterOf collects columns from one or more iterators into a Cols.
type ColsManager ¶
type ColsManager interface {
AddCol(...Col)
}
ColsManager adds columns to a collection.
type CombinationAddition ¶
type CombinationAddition interface {
Addition
All(SelectStatement) CombinationAddition
Distinct(SelectStatement) CombinationAddition
}
CombinationAddition is a set-operation addition (UNION/EXCEPT/INTERSECT).
type ComposedCondition ¶
type ComposedCondition struct {
ConditionMarker
// contains filtered or unexported fields
}
ComposedCondition joins conditions with a logical operator.
func (*ComposedCondition) IsNil ¶
func (c *ComposedCondition) IsNil() bool
type Condition ¶
type Condition struct {
ConditionMarker
// contains filtered or unexported fields
}
Condition is a single SQL condition expression.
Example ¶
f := Xor(
Or(
And(
nil,
CT[int]("a").AsCond(Lt(1)),
CT[string]("b").AsCond(LLike[string]("text")),
),
CT[int]("a").AsCond(Eq(2)),
),
CT[string]("b").AsCond(RLike[string]("g")),
)
Print(context.Background(), f)
f = Xor(
Or(
And(
(*Condition)(nil),
(*Condition)(nil),
(*Condition)(nil),
(*Condition)(nil),
CT[int]("c").AsCond(In(1, 2)),
CT[int]("c").AsCond(In(3, 4)),
CT[int]("a").AsCond(Eq(1)),
CT[string]("b").AsCond(Like("text")),
),
CT[int]("a").AsCond(Eq(2)),
),
CT[string]("b").AsCond(Like("g")),
)
Print(context.Background(), f)
Output: (((a < ?) AND (b LIKE ?)) OR (a = ?)) XOR (b LIKE ?) [1 %text 2 g%] (((c IN (?,?)) AND (c IN (?,?)) AND (a = ?) AND (b LIKE ?)) OR (a = ?)) XOR (b LIKE ?) [1 2 3 4 1 %text% 2 %g%]
type ConditionMarker ¶
type ConditionMarker interface {
// contains filtered or unexported methods
}
ConditionMarker marks condition fragments.
type Function ¶
type Function struct {
// contains filtered or unexported fields
}
Function is a SQL function call fragment.
Example ¶
PrintQuery(context.Background(), Count())
PrintQuery(context.Background(), Count(C("a")))
PrintQuery(context.Background(), Avg(C("a")))
PrintQuery(context.Background(), AnyValue(C("a")))
PrintQuery(context.Background(), Min(C("a")))
PrintQuery(context.Background(), Max(C("a")))
PrintQuery(context.Background(), First(C("a")))
PrintQuery(context.Background(), Last(C("a")))
PrintQuery(context.Background(), Sum(C("a")))
PrintQuery(context.Background(), Func(""))
PrintQuery(context.Background(), Func("COUNT"))
Output: COUNT(1) COUNT(a) AVG(a) ANY_VALUE(a) MIN(a) MAX(a) FIRST(a) LAST(a) SUM(a) COUNT(*)
type GroupByAddition ¶
type GroupByAddition interface {
Addition
Having(cond frag.Fragment) GroupByAddition
}
GroupByAddition is a GROUP BY clause.
func GroupBy ¶
func GroupBy(groups ...frag.Fragment) GroupByAddition
GroupBy builds a GROUP BY addition.
Example ¶
f := Select(ColsOf(C("F_a"), C("F_b"))).
From(
T("t_x"),
Where(Where(CT[int]("F_a").AsCond(Eq(1)))),
GroupBy(C("F_a"), C("F_b")).
Having(CT[int]("F_a").AsCond(Eq(1))),
Comment("group multi columns"),
)
Print(context.Background(), f)
Output: -- group multi columns SELECT f_a,f_b FROM t_x WHERE f_a = ? GROUP BY f_a,f_b HAVING f_a = ? [1 1]
type HasTableName ¶ added in v0.2.9
type HasTableName interface {
TableName() string
}
HasTableName exposes a table name.
type JoinAddition ¶
type JoinAddition interface {
Addition
On(condition frag.Fragment) JoinAddition
Using(cols ...Col) JoinAddition
}
JoinAddition is a JOIN clause.
func FullJoin ¶
func FullJoin(t frag.Fragment) JoinAddition
FullJoin builds a FULL JOIN on t. Unsupported on MySQL/SQLite.
func Join ¶
func Join(t frag.Fragment, methods ...string) JoinAddition
Join builds a JOIN on t with optional join methods.
Example ¶
f := Select(frag.Compose(", ",
Alias(tUser.C("f_id"), "f_user_id"),
Alias(tUser.C("f_org_id"), "f_org_id"),
Alias(tOrg.C("f_name"), "f_org_name"),
)).From(
tUser,
Join(Alias(tOrg, "t_org")).On(
And(
CC[int64](tUser.C("f_org_id")).AsCond(EqCol(CC[int64](tOrg.C("f_org_id")))),
CC[string](tOrg.C("f_name")).AsCond(Neq("abc")),
),
),
Comment("join on"),
)
Print(context.Background(), f)
f = Select(nil).
From(
tUser,
LeftJoin(tOrg).Using(tUser.C("f_org_id")),
Comment("join using"),
)
Print(context.Background(), f)
f = Select(
frag.Compose(
",",
Alias(C("f_id").Of(tUser), "f_user_id"),
Alias(C("f_org_id").Of(tOrg), "f_org_id"),
),
).From(
tUser,
RightJoin(tOrg).On(
CC[int64](tUser.C("f_org_id")).AsCond(EqCol(CC[int64](tOrg.C("f_org_id")))),
),
Comment("right join"),
)
Print(context.Background(), f)
f = Select(
frag.Compose(
",",
Alias(C("f_id").Of(tUser), "f_user_id"),
Alias(C("f_org_id").Of(tOrg), "f_org_id"),
),
).From(
tUser,
FullJoin(tOrg).On(
CC[int64](tUser.C("f_org_id")).AsCond(EqCol(CC[int64](tOrg.C("f_org_id")))),
),
Comment("full join"),
)
Print(context.Background(), f)
f = Select(
frag.Compose(
",",
Alias(C("f_id").Of(tUser), "f_user_id"),
Alias(C("f_org_id").Of(tOrg), "f_org_id"),
),
).From(
tUser,
InnerJoin(tOrg).On(
CC[int64](tUser.C("f_org_id")).AsCond(EqCol(CC[int64](tOrg.C("f_org_id")))),
),
Comment("inner join"),
)
Print(context.Background(), f)
f = Select(nil).
From(tUser, CrossJoin(tOrg), Comment("cross join"))
Print(context.Background(), f)
f = Select(
AutoAlias(
tUser.C("f_id"),
tOrg.C("f_name"),
),
).From(
tUser,
FullJoin(tOrg).On(
CC[int](tUser.C("f_org_id")).AsCond(EqCol(CC[int](tOrg.C("f_org_id")))),
),
Comment("full join + auto alias"),
)
Print(context.Background(), f)
Output: -- join on SELECT t_user.f_id AS f_user_id, t_user.f_org_id AS f_org_id, t_org.f_name AS f_org_name FROM t_user JOIN t_org AS t_org ON (t_user.f_org_id = t_org.f_org_id) AND (t_org.f_name <> ?) [abc] -- join using SELECT * FROM t_user LEFT JOIN t_org USING (f_org_id) [] -- right join SELECT t_user.f_id AS f_user_id,t_org.f_org_id AS f_org_id FROM t_user RIGHT JOIN t_org ON t_user.f_org_id = t_org.f_org_id [] -- full join SELECT t_user.f_id AS f_user_id,t_org.f_org_id AS f_org_id FROM t_user FULL JOIN t_org ON t_user.f_org_id = t_org.f_org_id [] -- inner join SELECT t_user.f_id AS f_user_id,t_org.f_org_id AS f_org_id FROM t_user INNER JOIN t_org ON t_user.f_org_id = t_org.f_org_id [] -- cross join SELECT * FROM t_user CROSS JOIN t_org [] -- full join + auto alias SELECT t_user.f_id AS t_user__f_id, t_org.f_name AS t_org__f_name FROM t_user FULL JOIN t_org ON t_user.f_org_id = t_org.f_org_id []
func RightJoin ¶
func RightJoin(t frag.Fragment) JoinAddition
RightJoin builds a RIGHT JOIN on t. Unsupported on SQLite.
type Key ¶
type Key interface {
frag.Fragment
ColIter
// Name returns the key/index name.
Name() string
// Of rebinds the key to the given table context.
Of(Table) Key
// IsPrimary reports whether this is a primary key.
IsPrimary() bool
// IsUnique reports whether this is a unique key.
IsUnique() bool
// String returns [$table_name.]$index_name.
String() string
}
Key is a table index or primary key.
type KeyColumnOption ¶
type KeyColumnOption = def.KeyColumnOption
KeyColumnOption is a per-column key option.
type KeyDef ¶
type KeyDef interface {
Method() string
ColumnOptions() []def.KeyColumnOption
}
KeyDef exposes index method and per-column options.
type KeyOption ¶
type KeyOption func(*key)
KeyOption configures a key at construction time.
func WithKeyColumnOptions ¶
func WithKeyColumnOptions(opts ...KeyColumnOption) KeyOption
WithKeyColumnOptions sets per-column key options.
func WithKeyMethod ¶
WithKeyMethod sets the index method (for example BTREE).
func WithKeyUniqueness ¶
WithKeyUniqueness marks the key as unique or non-unique.
type Keys ¶
type Keys interface {
KeyIter
KeyPick
// Of rebinds all keys to the given table context.
Of(Table) Keys
}
Keys is a set of keys.
type KeysManager ¶
type KeysManager interface {
AddKey(...Key)
}
KeysManager adds keys to a collection.
type LimitAddition ¶
type LimitAddition interface {
Addition
Offset(offset int64) LimitAddition
}
LimitAddition is a LIMIT clause.
func Limit ¶
func Limit(count int64) LimitAddition
Limit builds a LIMIT addition.
Example ¶
f := Select(nil).
From(
T("t_x"),
Where(CT[int]("F_a").AsCond(Eq(1))),
Limit(1),
Comment("limit"),
)
Print(context.Background(), f)
f = Select(nil).
From(
T("t_x"),
Where(CT[int]("F_a").AsCond(Eq(1))),
Limit(-1),
Comment("without limit"),
)
Print(context.Background(), f)
f = Select(nil).
From(
T("t_x"),
Where(CT[int]("F_a").AsCond(Eq(1))),
Limit(20).Offset(100),
Comment("limit with offset", "comment line2"),
)
Print(context.Background(), f)
Output: -- limit SELECT * FROM t_x WHERE f_a = ? LIMIT 1 [1] -- without limit SELECT * FROM t_x WHERE f_a = ? [1] -- limit with offset -- comment line2 SELECT * FROM t_x WHERE f_a = ? LIMIT 20 OFFSET 100 [1]
type Newer ¶ added in v0.3.1
type Newer interface {
New() Model
}
Newer creates a new model instance.
type OnConflictAddition ¶
type OnConflictAddition interface {
Addition
DoNothing() OnConflictAddition
DoUpdateSet(...Assignment) OnConflictAddition
}
OnConflictAddition is an ON CONFLICT clause.
func OnConflict ¶
func OnConflict(cols ColIter) OnConflictAddition
OnConflict builds an ON CONFLICT addition for cols.
type OrderAddition ¶
OrderAddition is an ORDER BY item.
func AscOrder ¶
func AscOrder(by frag.Fragment, ex ...frag.Fragment) OrderAddition
AscOrder asc order
type ReturningAddition ¶
type ReturningAddition interface {
Addition
}
ReturningAddition is a RETURNING clause.
func Returning ¶
func Returning(p frag.Fragment) ReturningAddition
Returning builds a RETURNING addition.
type SelectStatement ¶
SelectStatement is a SELECT statement fragment.
type SqlCondition ¶
type SqlCondition interface {
frag.Fragment
ConditionMarker
}
SqlCondition is a SQL boolean condition.
type StmtDelete ¶
type StmtDelete struct {
// contains filtered or unexported fields
}
StmtDelete builds a DELETE statement.
func Delete ¶
func Delete() *StmtDelete
Delete starts a DELETE statement builder.
Example ¶
f := Delete().From(
T("t_x"),
Where(CT[int]("F_a").AsCond(Eq(1))),
Comment("delete"),
)
Print(context.Background(), f)
Output: -- delete DELETE FROM t_x WHERE f_a = ? [1]
func (StmtDelete) From ¶
func (s StmtDelete) From(t Table, additions ...Addition) *StmtDelete
func (*StmtDelete) IsNil ¶
func (s *StmtDelete) IsNil() bool
type StmtInsert ¶
type StmtInsert struct {
// contains filtered or unexported fields
}
StmtInsert builds an INSERT statement.
func Insert ¶
func Insert(modifiers ...string) *StmtInsert
Insert starts an INSERT statement builder.
Example ¶
f := Insert().
Into(
T("t_user"),
Comment("insert"),
).
Values(Columns("f_a", "f_b"), 1, 2)
Print(context.Background(), f)
f = Insert("IGNORE").
Into(
T("t_user"),
Comment("insert ignore and multi"),
).
Values(Columns("f_a", "f_b"), 1, 2, 1, 2, 1, 2)
Print(context.Background(), f)
f = Insert().
Into(
T("t_user_migrated"),
Comment("insert from selection"),
).
Values(
Columns("f_a", "f_b"),
Select(Columns("f_a", "f_b")).
From(
T("t_user_previous"),
Where(CT[string]("f_status").AsCond(Eq("valid"))),
),
)
Print(context.Background(), f)
f = Insert().
Into(
T("t_user"),
OnConflict(ColsOf(C("f_id"))).DoNothing(),
Comment("insert on conflict do nothing"),
).
Values(ColsOf(C("f_id"), C("f_name")), 1, "saito")
Print(context.Background(), f)
f = Insert().
Into(
T("t_user"),
OnConflict(ColsOf(C("f_id"))).
DoUpdateSet(ColumnsAndValues(ColsOf(C("f_name")), "saito")),
Comment("insert on conflict do update"),
).
Values(ColsOf(C("f_id"), C("f_name")), 1, "saito")
Print(context.Background(), f)
f = Insert().
Into(
T("t_user"),
OnDuplicate(ColumnsAndValues(ColsOf(C("f_id")), C("f_id"))),
Comment("insert on duplicate key do update"),
).
Values(ColsOf(C("f_id"), C("f_name")), 1, "saito")
Print(context.Background(), f)
f = Insert().
Into(
T("t_user"),
OnConflict(ColsOf(C("f_id"))).
DoUpdateSet(
ColumnsAndValues(ColsOf(C("f_name")), "saito"),
nil,
),
Comment("with nil assignment"),
).
Values(ColsOf(C("f_id"), C("f_name")), 1, "saito")
Print(context.Background(), f)
Output: -- insert INSERT INTO t_user (f_a,f_b) VALUES (?,?) [1 2] -- insert ignore and multi INSERT IGNORE INTO t_user (f_a,f_b) VALUES (?,?), (?,?), (?,?) [1 2 1 2 1 2] -- insert from selection INSERT INTO t_user_migrated (f_a,f_b) SELECT f_a,f_b FROM t_user_previous WHERE f_status = ? [valid] -- insert on conflict do nothing INSERT INTO t_user (f_id,f_name) VALUES (?,?) ON CONFLICT (f_id) DO NOTHING [1 saito] -- insert on conflict do update INSERT INTO t_user (f_id,f_name) VALUES (?,?) ON CONFLICT (f_id) DO UPDATE SET f_name = ? [1 saito saito] -- insert on duplicate key do update INSERT INTO t_user (f_id,f_name) VALUES (?,?) ON DUPLICATE KEY UPDATE f_id = f_id [1 saito] -- with nil assignment INSERT INTO t_user (f_id,f_name) VALUES (?,?) ON CONFLICT (f_id) DO UPDATE SET f_name = ? [1 saito saito]
func (StmtInsert) Into ¶
func (s StmtInsert) Into(t Table, additions ...Addition) *StmtInsert
func (*StmtInsert) IsNil ¶
func (s *StmtInsert) IsNil() bool
func (StmtInsert) Values ¶
func (s StmtInsert) Values(cols Cols, values ...any) *StmtInsert
type StmtSelect ¶
type StmtSelect struct {
SelectStatement
// contains filtered or unexported fields
}
StmtSelect builds a SELECT statement.
func Select ¶
func Select(f frag.Fragment, modifiers ...frag.Fragment) *StmtSelect
Select starts a SELECT statement builder.
Example ¶
f := Select(
nil,
frag.Lit("SQL_CALC_FOUND_ROWS"),
).From(
tUser,
Where(CT[int]("F_created_at").AsCond(Gte(593650800))),
Limit(10),
Comment("select with modifier"),
)
Print(context.Background(), f)
f = Select(nil).From(
tUser,
Where(CT[int]("F_id").AsCond(In(1, 2, 3))),
OrderBy(
Order(tUser.C("f_id")),
AscOrder(tUser.C("f_org_id"), NullsFirst()),
DescOrder(tUser.C("f_name"), NullsLast()),
),
Comment("select with orders"),
)
Print(context.Background(), f)
f = Select(
frag.Compose(",",
DistinctOn(tUser.C("f_org_id")),
tUser.C("f_id"),
tUser.C("f_name"),
),
).From(
tUser,
OrderBy(Order(C("f_created_at"))),
Comment("select with distinct on"),
)
Print(context.Background(), f)
f = Select(nil).From(
tUser,
Where(CT[int]("F_id").AsCond(Eq(1))),
ForUpdateSkipLocked(),
Comment("select 1 row for update"),
)
Print(context.Background(), f)
f = Select(nil).From(
tUser,
Where(CT[int]("F_id").AsCond(Eq(1))),
ForUpdateNoWait(),
Comment("select 1 row for update"),
)
Print(context.Background(), f)
f = Select(nil).From(
tUser,
Where(CT[int]("F_id").AsCond(Eq(1))),
ForShareSkipLocked(),
Comment("select 1 row for share"),
)
Print(context.Background(), f)
f = Select(nil).From(
tUser,
Where(CT[int]("F_id").AsCond(Eq(1))),
ForShareNoWait(),
Comment("select 1 row for share"),
)
Print(context.Background(), f)
Output: -- select with modifier SELECT SQL_CALC_FOUND_ROWS * FROM t_user WHERE f_created_at >= ? LIMIT 10 [593650800] -- select with orders SELECT * FROM t_user WHERE f_id IN (?,?,?) ORDER BY (f_id),(f_org_id) ASC NULLS FIRST,(f_name) DESC NULLS LAST [1 2 3] -- select with distinct on SELECT DISTINCT ON (f_org_id),f_id,f_name FROM t_user ORDER BY (f_created_at) [] -- select 1 row for update SELECT * FROM t_user WHERE f_id = ? FOR UPDATE SKIP LOCKED [1] -- select 1 row for update SELECT * FROM t_user WHERE f_id = ? FOR UPDATE NOWAIT [1] -- select 1 row for share SELECT * FROM t_user WHERE f_id = ? FOR SHARE SKIP LOCKED [1] -- select 1 row for share SELECT * FROM t_user WHERE f_id = ? FOR SHARE NOWAIT [1]
func (StmtSelect) From ¶
func (s StmtSelect) From(t frag.Fragment, additions ...Addition) *StmtSelect
func (*StmtSelect) IsNil ¶
func (s *StmtSelect) IsNil() bool
type StmtUpdate ¶
type StmtUpdate struct {
// contains filtered or unexported fields
}
StmtUpdate builds an UPDATE statement.
func Update ¶
func Update(t Table, modifiers ...string) *StmtUpdate
Update starts an UPDATE statement on t.
Example ¶
var (
f_id = CT[int]("f_id")
f_stu_id = CT[int]("f_stu_id")
f_score = CT[int]("f_score")
f_class = CT[string]("f_class")
t_stu = T("t_stu", f_id, f_score, f_class)
t_class = T("t_class", f_stu_id, f_class)
)
f := Update(t_stu).
Set(
CC[int](t_stu.C("f_score")).AssignBy(Value(100)),
CC[string](t_stu.C("f_class")).AssignBy(AsValue(CC[string](t_class.C("f_class")))),
).
From(t_class).
Where(
CC[string](t_stu.C(f_id.Name())).
AsCond(EqCol(CC[string](t_class.C(f_stu_id.Name())))),
Comment("update from postgres supported"),
)
Print(context.Background(), f)
f = Update(t_stu).
From(
nil,
Join(t_class).On(
CC[string](t_stu.C(f_id.Name())).
AsCond(EqCol(CC[string](t_class.C(f_stu_id.Name())))),
),
Comment("update join mysql supported"),
).
Set(
CC[int](t_stu.C("f_score")).AssignBy(Value(100)),
CC[string](t_stu.C("f_class")).AssignBy(AsValue(CC[string](t_class.C("f_class")))),
)
Print(context.Background(), f)
sub := Select(f_class.Of(t_class)).From(
t_class,
Where(CC[int](f_stu_id.Of(t_class)).AsCond(EqCol(CC[int](f_id.Of(t_stu))))),
Limit(1),
)
f = Update(t_stu).
Set(
CC[int](t_stu.C("f_score")).AssignBy(Value(100)),
ColumnsAndValues(f_class.Of(t_stu), sub),
).
Where(
Exists(sub),
Comment("update with sub query and exists condition sqlite supported"),
)
Print(context.Background(), f)
f = Update(t_stu).
Set(
CC[int](t_stu.C("f_score")).AssignBy(Value(100)),
).
Where(
CC[int](t_stu.C("f_id")).AsCond(Eq(1)),
Returning(nil),
Comment("update with returning"),
)
Print(context.Background(), f)
f = UpdateIgnore(t_stu).
Set(CC[int](t_stu.C("f_score")).AssignBy(Value(100))).
Where(
CC[int](t_stu.C("f_id")).AsCond(Eq(1)),
Comment("update ignore"),
)
Print(context.Background(), f)
f = Update(t_stu).
Set(
ColumnsAndValues(t_stu.C("f_score"), t_stu.C("f_score").Fragment("(#+1)%100")),
).
Where(
CC[int](t_stu.C("f_id")).AsCond(Eq(1)),
Comment("update by column fragment"),
)
Print(context.Background(), f)
Output: -- update from postgres supported UPDATE t_stu SET f_score = ?, f_class = t_class.f_class FROM t_class WHERE t_stu.f_id = t_class.f_stu_id [100] -- update join mysql supported UPDATE t_stu JOIN t_class ON t_stu.f_id = t_class.f_stu_id SET f_score = ?, f_class = t_class.f_class [100] -- update with sub query and exists condition sqlite supported UPDATE t_stu SET f_score = ?, f_class = (SELECT f_class FROM t_class WHERE f_stu_id = f_id LIMIT 1) WHERE EXISTS (SELECT f_class FROM t_class WHERE f_stu_id = f_id LIMIT 1) [100] -- update with returning UPDATE t_stu SET f_score = ? WHERE f_id = ? RETURNING * [100 1] -- update ignore UPDATE IGNORE t_stu SET f_score = ? WHERE f_id = ? [100 1] -- update by column fragment UPDATE t_stu SET f_score = (f_score+1)%100 WHERE f_id = ? [1]
func UpdateIgnore ¶
func UpdateIgnore(t Table) *StmtUpdate
UpdateIgnore starts an UPDATE IGNORE statement on t.
func (StmtUpdate) From ¶
func (s StmtUpdate) From(from Table, additions ...Addition) *StmtUpdate
func (*StmtUpdate) IsNil ¶
func (s *StmtUpdate) IsNil() bool
func (StmtUpdate) Set ¶
func (s StmtUpdate) Set(assignments ...Assignment) *StmtUpdate
func (StmtUpdate) Where ¶
func (s StmtUpdate) Where(cond frag.Fragment, additions ...Addition) *StmtUpdate
type TCol ¶
type TCol[T any] interface { Col // AsCond builds a condition with the given valuator. AsCond(ColValuer[T]) frag.Fragment // AssignBy builds an assignment with the given valuators. AssignBy(...ColValuer[T]) Assignment }
TCol is a typed column that can form conditions and assignments.
type Table ¶
type Table interface {
// TableName returns the table name.
TableName() string
// String returns the table name.
String() string
KeyPick
KeyIter
ColPick
ColIter
// Fragment builds a SQL fragment with `#` as a table/column placeholder.
Fragment(string, ...any) frag.Fragment
frag.Fragment
}
Table is a database table with columns and keys.
func GetColTable ¶
GetColTable returns the table bound to c, unwrapping ColWrapper if needed.
type ToggleType ¶
type ToggleType int8
ToggleType is a SQL rendering toggle.
const ( // TOGGLE__MULTI_TABLE qualifies columns with table names. TOGGLE__MULTI_TABLE ToggleType = iota + 1 // TOGGLE__AUTO_ALIAS aliases multi-table columns automatically. TOGGLE__AUTO_ALIAS // TOGGLE__TUPLE_ASSIGNMENTS enables tuple-style assignments. TOGGLE__TUPLE_ASSIGNMENTS // TOGGLE__IN_PROJECT marks rendering inside a projection list. TOGGLE__IN_PROJECT // TOGGLE__SKIP_COMMENTS skips comment additions. TOGGLE__SKIP_COMMENTS // TOGGLE__SKIP_JOIN skips join additions. TOGGLE__SKIP_JOIN )
type Toggles ¶
type Toggles map[ToggleType]bool
Toggles is a set of enabled ToggleType values.
func TogglesFromContext ¶
TogglesFromContext returns toggles stored in ctx.
type WithColumnComment ¶
WithColumnComment provides per-field column comments.
type WithColumnDesc ¶
WithColumnDesc provides per-field column descriptions.
type WithColumnRel ¶
WithColumnRel provides per-field column relations.
type WithDatatypeDesc ¶
WithDatatypeDesc provides a driver-specific datatype override.
type WithIndexes ¶
type WithIndexes interface {
// Indexes returns field name => []string{index name, options...}
Indexes() map[string][]string
}
WithIndexes provides non-unique index definitions.
type WithPrimaryKey ¶
type WithPrimaryKey interface {
PrimaryKey() []string
}
WithPrimaryKey provides primary key field names.
type WithSchema ¶
WithSchema returns a copy with a schema.
type WithStmt ¶
type WithStmt struct {
// contains filtered or unexported fields
}
WithStmt builds a WITH/CTE statement.
func WithRecursive ¶
WithRecursive starts a recursive WITH statement.
type WithTableDesc ¶
type WithTableDesc interface {
TableDesc() []string
}
WithTableDesc provides table description lines.
type WithTableName ¶
WithTableName returns a copy with a different table name.
type WithUniqueIndexes ¶
type WithUniqueIndexes interface {
// UniqueIndexes returns field name => []string{index name, options...}
UniqueIndexes() map[string][]string
}
WithUniqueIndexes provides unique index definitions.
Source Files
¶
- def_col.go
- def_key.go
- def_model.go
- def_table.go
- doc.go
- expr_addition.go
- expr_addition_combination.go
- expr_addition_comment.go
- expr_addition_for_share.go
- expr_addition_for_update.go
- expr_addition_group_by.go
- expr_addition_join.go
- expr_addition_limit.go
- expr_addition_on_conflict.go
- expr_addition_on_duplicate.go
- expr_addition_order_by.go
- expr_addition_returning.go
- expr_addition_where.go
- expr_alias.go
- expr_assignment.go
- expr_condition.go
- expr_condition_exists.go
- expr_function.go
- expr_stmt_delete.go
- expr_stmt_insert.go
- expr_stmt_select.go
- expr_stmt_update.go
- expr_stmt_with.go
- scan.go
- toggle.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package modeled provides builder Table, Col, and Key variants parameterized by a concrete Model, so the compiler knows which model a fragment belongs to.
|
Package modeled provides builder Table, Col, and Key variants parameterized by a concrete Model, so the compiler knows which model a fragment belongs to. |