sqlx

package module
v0.24.0 Latest Latest
Warning

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

Go to latest
Published: Mar 30, 2023 License: Apache-2.0 Imports: 15 Imported by: 0

README

SQL builder for Go 1.18+ Build Status GoDoc License

Package sqlx provides a set of flexible and powerful SQL builders, not ORM, which is inspired by go-sqlbuilder. The built result can be used by DB.Query() and DB.Exec()

Install

$ go get -u github.com/xgfone/sqlx

Usage

package main

import (
    "fmt"

    "github.com/xgfone/sqlx"
)

func main() {
    builder := sqlx.Select("*").From("table")
    builder.Where(sqlx.Equal("id", 123), builder.Between("age", 20, 30))

    // You can set the dialect by hand, which is DefaultDialect by default.
    // DefaultDialect is the MySQL dialect, but you can modify it.
    // builder.SetDialect(Sqlite3)

    sql, args := builder.Build()
    fmt.Println(sql)
    fmt.Println(args)

    // Output:
    // SELECT * FROM `table` WHERE `id`=? AND `age` BETWEEN ? AND ?
    // [123 20 30]
}

You can use sqlx.DB, which is the proxy of builder and sql.DB, it will automatically set the dialect by the sql driver name. For example,

// Set the dialect to MySQL.
db, _ := sqlx.Open("mysql", "user:password@tcp(127.0.0.1:3306)/db")
builder := db.Select("*").From("table").Where(sqlx.Equal("id", 123))

sql, args := builder.Build()
rows, err := db.Query(sql, args...)

// Or
// rows, err := builder.Query()
Intercept SQL
package main

import (
    "fmt"

    "github.com/xgfone/sqlx"
)

func main() {
    // Open DB connecting the mysql server and set the dialect to MySQL.
    db, err := sqlx.Open("mysql", "user:password@tcp(127.0.0.1:3306)/db")
    if err != nil {
        fmt.Println(err)
        return
    }
    defer db.Close()

    // Set the interceptor to print the sql statement.
    db.Interceptor = func(sql string, args []interface{}) (string, []interface{}) {
        fmt.Println(sql)
        return sql, args
    }

    // Build the SELECT SQL statement
    builder := db.Select("*").From("table")
    builder.Where(builder.Equal("id", 123))
    rows, err := builder.Query()
    // ...

    // Interceptor will output:
    // SELECT * FROM `table` WHERE `id`=?
}

Documentation

Overview

Package sqlx is a set of the simple, flexible and powerful SQL builders with zero-config.

Index

Examples

Constants

View Source
const DateTimeZero = "0000-00-00 00:00:00"

DateTimeZero is the ZERO of the sql datetime.

Variables

View Source
var (
	ColumnID        = NewColumn("id")
	ColumnCreatedAt = NewColumn("created_at")
	ColumnDeletedAt = NewColumn("deleted_at")
	ColumnUpdatedAt = NewColumn("updated_at")
)

Pre-define some common columns.

View Source
var ArgsDefaultCap = 4

ArgsDefaultCap is the default capacity to be allocated for ArgsBuilder.

View Source
var BufferDefaultCap = 64

BufferDefaultCap is the default capacity to be allocated for buffer from pool.

View Source
var DefaultConfigs = []Config{MaxOpenConns(0)}

DefaultConfigs is the default configs.

View Source
var DefaultDB = new(DB)

DefaultDB is the default global DB.

View Source
var DefaultDialect = MySQL

DefaultDialect is the default dialect.

View Source
var Sep = "_"

Sep is the separator by the select struct.

Functions

func CheckErrNoRows added in v0.17.0

func CheckErrNoRows(err error) (exist bool, e error)

CheckErrNoRows extracts the error sql.ErrNoRows as the bool, which returns

  • (true, nil) if err is equal to nil
  • (false, nil) if err is equal to sql.ErrNoRows
  • (false, err) if err is equal to others

func ColumnsContain added in v0.17.0

func ColumnsContain(columns []Column, column Column) bool

ColumnsContain reports whether the columns contains the column.

Notice: it only compares the field Name.

func ConditionsContain added in v0.18.0

func ConditionsContain(conditions []Condition, column Column) bool

ConditionsContain reports whether the conditions contains the column.

func RegisterDialect

func RegisterDialect(dialect Dialect, force bool)

RegisterDialect registers the Dialect with the name.

If the name has been registered, it will panic. But you can set force to true to ignore it.

func ScanColumnsToStruct added in v0.3.0

func ScanColumnsToStruct(scan func(...interface{}) error, columns []string, s interface{}) (err error)

ScanColumnsToStruct scans the columns into the fields of the struct s, which supports the tag named "sql" to modify the field name.

If the value of the tag is "-", however, the field will be ignored. If the tag contains the attribute "notpropagate", for the embeded struct, do not scan the fields of the embeded struct.

func ScanRow added in v0.18.1

func ScanRow(scan func(dests ...interface{}) error, dests ...interface{}) error

ScanRow uses the function scan to scan the sql row into dests, which may be used as a proxy of the function sql.Row.Scan or sql.Rows.Scan.

If the dest value is the basic builtin types as follow, it will be wrapped to support the sql NULL and the converting from other types.

*time.Duration:
    string:    time.ParseDuration(src)
    []byte:    time.ParseDuration(string(src))
    int64:     time.Duration(src) * time.Millisecond
    float64:   time.Duration(src * float64(time.Second))
*time.Time:
    int64:     time.Unix(src, 0).In(Location)
    float64:   time.Unix(Integer, Fraction).In(Location)
    string:    time.ParseInLocation(DatetimeLayout, src, Location))
    []byte:    time.ParseInLocation(DatetimeLayout, string(src), Location))
    time.Time: src
*bool:
     bool:     src
     int64:    src!=0
     float64:  src!=0
     string:   strconv.ParseBool(src)
     []byte:
               len(src)==1: src[0] != '\x00'
               len(src)!=1: strconv.ParseBool(string(src))
*string:
    string:    src
    []byte:    string(src)
    bool:      "true" or "false"
    int64:     strconv.FormatInt(src, 10)
    float64:   strconv.FormatFloat(src, 'f', -1, 64)
    time.Time: src.In(Location).Format(DatetimeLayout)
*float32, *float64:
    bool:      true=>1, false=>0
    int64:     floatXX(src)
    float64:   floatXX(src)
    string:    strconv.ParseFloat(src, 64)
    []byte:    strconv.ParseFloat(string(src), 64)
*int, *int8, *int16, *int32, *int64:
	bool:      true=>1, false=>0
    int64:     intXX(src)
    float64:   intXX(src)
    string:    strconv.ParseInt(src, 10, 64)
    []byte:    strconv.ParseInt(string(src), 10, 64)
    time.Time: src.Unix() only for int/int64
*uint, *uint8, *uint16, *uint32, *uint64:
	bool:      true=>1, false=>0
    int64:     uintXX(src)
    float64:   uintXX(src)
    string:    strconv.ParseUint(src, 10, 64)
    []byte:    strconv.ParseUint(string(src), 10, 64)
    time.Time: src.Unix() only for uint/uint64

func SetConnURLLocation added in v0.13.0

func SetConnURLLocation(connURL string, loc *time.Location) string

SetConnURLLocation sets the argument "loc" in the connection url if missing.

If loc is nil, use Location instead.

Types

type ArgsBuilder

type ArgsBuilder struct {
	Dialect
	// contains filtered or unexported fields
}

ArgsBuilder is used to build the arguments.

func NewArgsBuilder

func NewArgsBuilder(dialect Dialect) *ArgsBuilder

NewArgsBuilder returns a new ArgsBuilder.

func (*ArgsBuilder) Add

func (a *ArgsBuilder) Add(arg interface{}) (placeholder string)

Add appends the argument and returns the its placeholder.

If arg is the type of sql.NamedArg, it will use @arg.Name as the placeholder and arg.Value as the value.

func (*ArgsBuilder) Args

func (a *ArgsBuilder) Args() []interface{}

Args returns the added arguments.

type Base added in v0.19.0

type Base struct {
	ID        int  `sql:"id,omitempty" json:"Id,omitempty"`
	DeletedAt Time `sql:"deleted_at,omitempty" json:"-"`
	CreatedAt Time `sql:"created_at,omitempty"`
	UpdatedAt Time `sql:"updated_at,omitempty"`
}

Base is the common columns of the sql table.

type Builder

type Builder interface {
	// Build is used to build the sql statement.
	Build() (sql string, args []interface{})
}

Builder is the SQL builder interface.

type Column

type Column struct {
	Name  string
	Table string
	Alias string
	Value interface{}
}

Column represents the column of the SQL table.

func NewColumn added in v0.12.0

func NewColumn(colName string) Column

NewColumn returns the new Column with the column name.

func (Column) Add added in v0.12.0

func (c Column) Add(value interface{}) ColumnSetter

Add is equal to Add(c.FullName(), value).

func (Column) Assign added in v0.12.0

func (c Column) Assign(value interface{}) ColumnSetter

Assign is the alias of the method Set.

func (Column) Between added in v0.12.0

func (c Column) Between(lower, upper interface{}) ColumnCondition

Between is equal to Between(c.FullName(), lower, upper).

func (Column) ColEq added in v0.12.0

func (c Column) ColEq(otherColumn string) Condition

ColEq is equal to ColEq(c.FullName(), otherColumn).

func (Column) ColGt added in v0.12.0

func (c Column) ColGt(otherColumn string) Condition

ColGt is equal to ColGt(c.FullName(), otherColumn).

func (Column) ColGtEq added in v0.12.0

func (c Column) ColGtEq(otherColumn string) Condition

ColGtEq is equal to ColGtEq(c.FullName(), otherColumn).

func (Column) ColLe added in v0.12.0

func (c Column) ColLe(otherColumn string) Condition

ColLe is equal to ColLe(c.FullName(), otherColumn).

func (Column) ColLeEq added in v0.12.0

func (c Column) ColLeEq(otherColumn string) Condition

ColLeEq is equal to ColLeEq(c.FullName(), otherColumn).

func (Column) ColNotEq added in v0.12.0

func (c Column) ColNotEq(otherColumn string) Condition

ColNotEq is equal to ColNotEq(c.FullName(), otherColumn).

func (Column) ColumnEqual added in v0.12.0

func (c Column) ColumnEqual(otherColumn string) Condition

ColumnEqual is equal to ColumnEqual(c.FullName(), otherColumn).

func (Column) ColumnGreater added in v0.12.0

func (c Column) ColumnGreater(otherColumn string) Condition

ColumnGreater is equal to ColumnGreater(c.FullName(), otherColumn).

func (Column) ColumnGreaterEqual added in v0.12.0

func (c Column) ColumnGreaterEqual(otherColumn string) Condition

ColumnGreaterEqual is equal to ColumnGreaterEqual(c.FullName(), otherColumn).

func (Column) ColumnLess added in v0.12.0

func (c Column) ColumnLess(otherColumn string) Condition

ColumnLess is equal to ColumnLess(c.FullName(), otherColumn).

func (Column) ColumnLessEqual added in v0.12.0

func (c Column) ColumnLessEqual(otherColumn string) Condition

ColumnLessEqual is equal to ColumnLessEqual(c.FullName(), otherColumn).

func (Column) ColumnNotEqual added in v0.12.0

func (c Column) ColumnNotEqual(otherColumn string) Condition

ColumnNotEqual is equal to ColumnNotEqual(c.FullName(), otherColumn).

func (Column) Dec added in v0.12.0

func (c Column) Dec() ColumnSetter

Dec is equal to Dec(c.FullName(), value).

func (Column) Div added in v0.12.0

func (c Column) Div(value interface{}) ColumnSetter

Div is equal to Div(c.FullName(), value).

func (Column) Eq added in v0.12.0

func (c Column) Eq(value interface{}) ColumnCondition

Eq is equal to Eq(c.FullName(), value).

func (Column) Equal added in v0.12.0

func (c Column) Equal(value interface{}) ColumnCondition

Equal is equal to Equal(c.FullName(), value).

func (Column) EqualColumn added in v0.19.0

func (c Column) EqualColumn(other Column) Condition

EqualColumn is equal to ColumnEqual(c.FullName(), other.FullName()).

func (Column) FromTable added in v0.17.0

func (c Column) FromTable(t Table) Column

FromTable returns a new Column wit the table name from t.

func (Column) FullName added in v0.22.0

func (c Column) FullName() string

FullName returns the full name of the column, that's, it returns "Table.Name" if Table is not empty. Or return Column.

func (Column) Greater added in v0.12.0

func (c Column) Greater(value interface{}) ColumnCondition

Greater is equal to Greater(c.FullName(), value).

func (Column) GreaterColumn added in v0.19.0

func (c Column) GreaterColumn(other Column) Condition

GreaterColumn is equal to ColumnGreater(c.FullName(), other.FullName()).

func (Column) GreaterEqual added in v0.12.0

func (c Column) GreaterEqual(value interface{}) ColumnCondition

GreaterEqual is equal to GreaterEqual(c.FullName(), value).

func (Column) GreaterEqualColumn added in v0.19.0

func (c Column) GreaterEqualColumn(other Column) Condition

GreaterEqualColumn is equal to ColumnGreaterEqual(c.FullName(), other.FullName()).

func (Column) Gt added in v0.12.0

func (c Column) Gt(value interface{}) ColumnCondition

Gt is equal to Gt(c.FullName(), value).

func (Column) GtEq added in v0.12.0

func (c Column) GtEq(value interface{}) ColumnCondition

GtEq is equal to GtEq(c.FullName(), value).

func (Column) In added in v0.12.0

func (c Column) In(values ...interface{}) ColumnCondition

In is equal to In(c.FullName(), value).

func (Column) Inc added in v0.12.0

func (c Column) Inc() ColumnSetter

Inc is equal to Inc(c.FullName(), value).

func (Column) IsNotNull added in v0.12.0

func (c Column) IsNotNull() ColumnCondition

IsNotNull is equal to IsNotNull(c.FullName()).

func (Column) IsNull added in v0.12.0

func (c Column) IsNull() ColumnCondition

IsNull is equal to IsNull(c.FullName()).

func (Column) Le added in v0.12.0

func (c Column) Le(value interface{}) ColumnCondition

Le is equal to Le(c.FullName(), value).

func (Column) LeEq added in v0.12.0

func (c Column) LeEq(value interface{}) ColumnCondition

LeEq is equal to LeEq(c.FullName(), value).

func (Column) Less added in v0.12.0

func (c Column) Less(value interface{}) ColumnCondition

Less is equal to Less(c.FullName(), value).

func (Column) LessColumn added in v0.19.0

func (c Column) LessColumn(other Column) Condition

LessColumn is equal to ColumnLess(c.FullName(), other.FullName()).

func (Column) LessEqual added in v0.12.0

func (c Column) LessEqual(value interface{}) ColumnCondition

LessEqual is equal to LessEqual(c.FullName(), value).

func (Column) LessEqualColumn added in v0.19.0

func (c Column) LessEqualColumn(other Column) Condition

LessEqualColumn is equal to ColumnLessEqual(c.FullName(), other.FullName()).

func (Column) Like added in v0.12.0

func (c Column) Like(value string) ColumnCondition

Like is equal to Like(c.FullName(), value).

func (Column) Mul added in v0.12.0

func (c Column) Mul(value interface{}) ColumnSetter

Mul is equal to Mul(c.FullName(), value).

func (Column) NamedArg added in v0.12.0

func (c Column) NamedArg() sql.NamedArg

NamedArg implements the interface NamedArg to convert itself to sql.NamedArg.

func (Column) NotBetween added in v0.12.0

func (c Column) NotBetween(lower, upper interface{}) ColumnCondition

NotBetween is equal to NotBetween(c.FullName(), lower, upper).

func (Column) NotEq added in v0.12.0

func (c Column) NotEq(value interface{}) ColumnCondition

NotEq is equal to NotEq(c.FullName(), value).

func (Column) NotEqual added in v0.12.0

func (c Column) NotEqual(value interface{}) ColumnCondition

NotEqual is equal to NotEqual(c.FullName(), value).

func (Column) NotEqualColumn added in v0.19.0

func (c Column) NotEqualColumn(other Column) Condition

NotEqualColumn is equal to ColumnNotEqual(c.FullName(), other.FullName()).

func (Column) NotIn added in v0.12.0

func (c Column) NotIn(values ...interface{}) ColumnCondition

NotIn is equal to NotIn(c.FullName(), values...).

func (Column) NotLike added in v0.12.0

func (c Column) NotLike(value string) ColumnCondition

NotLike is equal to NotLike(c.FullName(), value).

func (Column) Set added in v0.12.0

func (c Column) Set(value interface{}) ColumnSetter

Set is equal to Set(c.FullName(), value).

func (Column) Sub added in v0.12.0

func (c Column) Sub(value interface{}) ColumnSetter

Sub is equal to Sub(c.FullName(), value).

func (Column) WithAlias added in v0.12.0

func (c Column) WithAlias(alias string) Column

WithAlias returns a new Column, based on the old column, with the alias name.

func (Column) WithTable added in v0.12.0

func (c Column) WithTable(tname string) Column

WithTable returns a new Column, based on the old column, with the table name.

func (Column) WithValue added in v0.12.0

func (c Column) WithValue(value interface{}) Column

WithValue returns a new Column, based on the old column, with the value.

type ColumnCondition added in v0.15.0

type ColumnCondition interface {
	Column() string
	Condition
}

ColumnCondition is the same as Condition with the column.

func Between

func Between(column string, lower, upper interface{}) ColumnCondition

Between returns a "column BETWEEN lower AND upper" expression.

func Eq added in v0.10.0

func Eq(column string, value interface{}) ColumnCondition

Eq is the short for Equal.

func Equal

func Equal(column string, value interface{}) ColumnCondition

Equal returns a "column=value" expression.

func Greater

func Greater(column string, value interface{}) ColumnCondition

Greater returns a "column>value" expression.

func GreaterEqual

func GreaterEqual(column string, value interface{}) ColumnCondition

GreaterEqual returns a "column>=value" expression.

func Gt added in v0.10.0

func Gt(column string, value interface{}) ColumnCondition

Gt is the short for Greater.

func GtEq added in v0.10.0

func GtEq(column string, value interface{}) ColumnCondition

GtEq is the short for GreaterEqual.

func In

func In(column string, values ...interface{}) ColumnCondition

In returns a "column IN (values...)" expression.

func IsNotNull

func IsNotNull(column string) ColumnCondition

IsNotNull returns a "column IS NOT NULL" expression.

func IsNull

func IsNull(column string) ColumnCondition

IsNull returns a "column IS NULL" expression.

func Le added in v0.10.0

func Le(column string, value interface{}) ColumnCondition

Le is the short for Less.

func LeEq added in v0.10.0

func LeEq(column string, value interface{}) ColumnCondition

LeEq is the short for LessEqual.

func Less

func Less(column string, value interface{}) ColumnCondition

Less returns a "column<value" expression.

func LessEqual

func LessEqual(column string, value interface{}) ColumnCondition

LessEqual returns a "column<=value" expression.

func Like

func Like(column string, value string) ColumnCondition

Like returns a "column LIKE value" expression.

Notice: if value does not contain the character '%', it will be formatted to fmt.Sprintf("%%%s%%", value).

func NotBetween

func NotBetween(column string, lower, upper interface{}) ColumnCondition

NotBetween returns a "column NOT BETWEEN lower AND upper" expression.

func NotEq added in v0.10.0

func NotEq(column string, value interface{}) ColumnCondition

NotEq is the short for NotEqual.

func NotEqual

func NotEqual(column string, value interface{}) ColumnCondition

NotEqual returns a "column<>value" expression.

func NotIn

func NotIn(column string, values ...interface{}) ColumnCondition

NotIn returns a "column NOT IN (values...)" expression.

func NotLike

func NotLike(column string, value string) ColumnCondition

NotLike returns a "column NOT LIKE value" expression.

Notice: if value does not contain the character '%', it will be formatted to fmt.Sprintf("%%%s%%", value).

type ColumnSetter added in v0.15.0

type ColumnSetter interface {
	Column() string
	Setter
}

ColumnSetter is the same as Setter with the column.

func Add

func Add(column string, value interface{}) ColumnSetter

Add represents SET "column = column + value" in UPDATE.

func Assign

func Assign(column string, value interface{}) ColumnSetter

Assign is the alias of Assign.

func Dec added in v0.12.0

func Dec(column string) ColumnSetter

Dec represents SET "column = column - 1" in UPDATE.

func Div

func Div(column string, value interface{}) ColumnSetter

Div represents SET "column = column / value" in UPDATE.

func Inc added in v0.12.0

func Inc(column string) ColumnSetter

Inc represents SET "column = column + 1" in UPDATE.

func Mul

func Mul(column string, value interface{}) ColumnSetter

Mul represents SET "column = column * value" in UPDATE.

func Set added in v0.10.0

func Set(column string, value interface{}) ColumnSetter

Set returns a "column=value" set statement.

func Sub

func Sub(column string, value interface{}) ColumnSetter

Sub represents SET "column = column - value" in UPDATE.

type Condition

type Condition interface {
	// BuildCondition builds and returns the condition expression.
	//
	// If there are some arguments, they should be added into ArgsBuilder.
	BuildCondition(*ArgsBuilder) string
}

Condition represents a condition of the WHERE statement.

func And

func And(exprs ...Condition) Condition

And returns an AND expression.

func ColEq added in v0.10.0

func ColEq(c1, c2 string) Condition

ColEq is the short for ColumnEqual.

func ColGt added in v0.10.0

func ColGt(c1, c2 string) Condition

ColGt is the short for ColumnGreater.

func ColGtEq added in v0.10.0

func ColGtEq(c1, c2 string) Condition

ColGtEq is the short for ColumnGreaterEqual.

func ColLe added in v0.10.0

func ColLe(c1, c2 string) Condition

ColLe is the short for ColumnLess.

func ColLeEq added in v0.10.0

func ColLeEq(c1, c2 string) Condition

ColLeEq is the short for ColumnLessEqual.

func ColNotEq added in v0.10.0

func ColNotEq(c1, c2 string) Condition

ColNotEq is the short for ColumnNotEqual.

func ColumnCond added in v0.12.0

func ColumnCond(left, op, right string) Condition

ColumnCond returns a Condition to operate two columns.

For example,

Column("column1", "=", "column2") ==> "column1 = column2"

However, both column1 and column2 are escaped by the dialect.

func ColumnEqual

func ColumnEqual(column1, column2 string) Condition

ColumnEqual is equal to Column(column1, "=", column2).

func ColumnGreater

func ColumnGreater(column1, column2 string) Condition

ColumnGreater is equal to Column(column1, ">", column2).

func ColumnGreaterEqual

func ColumnGreaterEqual(column1, column2 string) Condition

ColumnGreaterEqual is equal to Column(column1, ">=", column2).

func ColumnLess

func ColumnLess(column1, column2 string) Condition

ColumnLess is equal to Column(column1, "<", column2).

func ColumnLessEqual

func ColumnLessEqual(column1, column2 string) Condition

ColumnLessEqual is equal to Column(column1, "<=", column2).

func ColumnNotEqual

func ColumnNotEqual(column1, column2 string) Condition

ColumnNotEqual is equal to Column(column1, "<>", column2).

func Or

func Or(exprs ...Condition) Condition

Or returns an OR expression.

type ConditionSet added in v0.10.0

type ConditionSet struct{}

ConditionSet collects some WHERE conditions together.

func (ConditionSet) And added in v0.10.0

func (c ConditionSet) And(exprs ...Condition) Condition

And is a proxy of And.

func (ConditionSet) Between added in v0.10.0

func (c ConditionSet) Between(column string, lower, upper interface{}) ColumnCondition

Between is a proxy of Between.

func (ConditionSet) ColEq added in v0.10.0

func (c ConditionSet) ColEq(c1, c2 string) Condition

ColEq is the short for ColumnEqual.

func (ConditionSet) ColGt added in v0.10.0

func (c ConditionSet) ColGt(c1, c2 string) Condition

ColGt is the short for ColumnGreater.

func (ConditionSet) ColGtEq added in v0.10.0

func (c ConditionSet) ColGtEq(c1, c2 string) Condition

ColGtEq is the short for ColumnGreaterEqual.

func (ConditionSet) ColLe added in v0.10.0

func (c ConditionSet) ColLe(c1, c2 string) Condition

ColLe is the short for ColumnLess.

func (ConditionSet) ColLeEq added in v0.10.0

func (c ConditionSet) ColLeEq(c1, c2 string) Condition

ColLeEq is the short for ColumnLessEqual.

func (ConditionSet) ColNotEq added in v0.10.0

func (c ConditionSet) ColNotEq(c1, c2 string) Condition

ColNotEq is the short for ColumnNotEqual.

func (ConditionSet) ColumnCond added in v0.12.0

func (c ConditionSet) ColumnCond(left, op, right string) Condition

ColumnCond is a proxy of Column.

func (ConditionSet) ColumnEqual added in v0.10.0

func (c ConditionSet) ColumnEqual(column1, column2 string) Condition

ColumnEqual is a proxy of ColumnEqual.

func (ConditionSet) ColumnGreater added in v0.10.0

func (c ConditionSet) ColumnGreater(column1, column2 string) Condition

ColumnGreater is a proxy of ColumnGreater.

func (ConditionSet) ColumnGreaterEqual added in v0.10.0

func (c ConditionSet) ColumnGreaterEqual(column1, column2 string) Condition

ColumnGreaterEqual is a proxy of ColumnGreaterEqual.

func (ConditionSet) ColumnLess added in v0.10.0

func (c ConditionSet) ColumnLess(column1, column2 string) Condition

ColumnLess is a proxy of ColumnLess.

func (ConditionSet) ColumnLessEqual added in v0.10.0

func (c ConditionSet) ColumnLessEqual(column1, column2 string) Condition

ColumnLessEqual is a proxy of ColumnLessEqual.

func (ConditionSet) ColumnNotEqual added in v0.10.0

func (c ConditionSet) ColumnNotEqual(column1, column2 string) Condition

ColumnNotEqual is a proxy of ColumnNotEqual.

func (ConditionSet) Eq added in v0.10.0

func (c ConditionSet) Eq(col string, v interface{}) ColumnCondition

Eq is the short for Equal.

func (ConditionSet) Equal added in v0.10.0

func (c ConditionSet) Equal(column string, value interface{}) ColumnCondition

Equal is a proxy of Equal

func (ConditionSet) Greater added in v0.10.0

func (c ConditionSet) Greater(column string, value interface{}) ColumnCondition

Greater is a proxy of Greater.

func (ConditionSet) GreaterEqual added in v0.10.0

func (c ConditionSet) GreaterEqual(column string, value interface{}) ColumnCondition

GreaterEqual is a proxy of GreaterEqual.

func (ConditionSet) Gt added in v0.10.0

func (c ConditionSet) Gt(col string, v interface{}) ColumnCondition

Gt is the short for Greater.

func (ConditionSet) GtEq added in v0.10.0

func (c ConditionSet) GtEq(col string, v interface{}) ColumnCondition

GtEq is the short for GreaterEqual.

func (ConditionSet) In added in v0.10.0

func (c ConditionSet) In(column string, values ...interface{}) ColumnCondition

In is a proxy of In.

func (ConditionSet) IsNotNull added in v0.10.0

func (c ConditionSet) IsNotNull(column string) ColumnCondition

IsNotNull is a proxy of IsNotNull.

func (ConditionSet) IsNull added in v0.10.0

func (c ConditionSet) IsNull(column string) ColumnCondition

IsNull is a proxy of IsNull.

func (ConditionSet) Le added in v0.10.0

func (c ConditionSet) Le(col string, v interface{}) ColumnCondition

Le is the short for Less.

func (ConditionSet) LeEq added in v0.10.0

func (c ConditionSet) LeEq(col string, v interface{}) ColumnCondition

LeEq is the short for LessEqual.

func (ConditionSet) Less added in v0.10.0

func (c ConditionSet) Less(column string, value interface{}) ColumnCondition

Less is a proxy of Less.

func (ConditionSet) LessEqual added in v0.10.0

func (c ConditionSet) LessEqual(column string, value interface{}) ColumnCondition

LessEqual is a proxy of LessEqual.

func (ConditionSet) Like added in v0.10.0

func (c ConditionSet) Like(column string, value string) ColumnCondition

Like is a proxy of Like.

func (ConditionSet) NotBetween added in v0.10.0

func (c ConditionSet) NotBetween(column string, lower, upper interface{}) ColumnCondition

NotBetween is a proxy of NotBetween.

func (ConditionSet) NotEq added in v0.10.0

func (c ConditionSet) NotEq(col string, v interface{}) ColumnCondition

NotEq is the short for NotEqual.

func (ConditionSet) NotEqual added in v0.10.0

func (c ConditionSet) NotEqual(column string, value interface{}) ColumnCondition

NotEqual is a proxy of NotEqual.

func (ConditionSet) NotIn added in v0.10.0

func (c ConditionSet) NotIn(column string, values ...interface{}) ColumnCondition

NotIn is a proxy of NotIn.

func (ConditionSet) NotLike added in v0.10.0

func (c ConditionSet) NotLike(column string, value string) ColumnCondition

NotLike is a proxy of NotLike.

func (ConditionSet) Or added in v0.10.0

func (c ConditionSet) Or(exprs ...Condition) Condition

Or is a proxy of Or.

type Config added in v0.13.0

type Config func(*DB)

Config is used to configure the DB.

func ConnMaxIdleTime added in v0.13.0

func ConnMaxIdleTime(d time.Duration) Config

ConnMaxIdleTime returns a Config to set the maximum idle time of the connection.

func ConnMaxLifetime added in v0.13.0

func ConnMaxLifetime(d time.Duration) Config

ConnMaxLifetime returns a Config to set the maximum lifetime of the connection.

func MaxIdleConns added in v0.13.0

func MaxIdleConns(n int) Config

MaxIdleConns returns a Config to set the maximum number of the idle connection.

func MaxOpenConns added in v0.13.0

func MaxOpenConns(maxnum int) Config

MaxOpenConns returns a Config to set the maximum number of the open connection.

If maxnum is equal to or less than 0, it is runtime.NumCPU()*2 by default.

type DB

type DB struct {
	*sql.DB
	Dialect
	Executor
	Interceptor
}

DB is the wrapper of the sql.DB.

func Open

func Open(driverName, dataSourceName string, configs ...Config) (*DB, error)

Open opens a database specified by its database driver name and a driver-specific data source name,

func (*DB) CreateTable

func (db *DB) CreateTable(table string) *TableBuilder

CreateTable returns a SQL table builder.

func (*DB) Delete

func (db *DB) Delete(tables ...string) *DeleteBuilder

Delete returns a DELETE SQL builder.

func (*DB) ExecContext added in v0.11.0

func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)

ExecContext executes the sql statement.

func (*DB) GetExecutor added in v0.22.2

func (db *DB) GetExecutor() Executor

GetExecutor returns the executor if set. Or, return sql.DB instead.

func (*DB) Insert

func (db *DB) Insert() *InsertBuilder

Insert returns a INSERT SQL builder.

func (*DB) NewTable added in v0.17.0

func (db *DB) NewTable(name string) Table

NewTable returns a new Table with the db.

func (*DB) QueryContext added in v0.11.0

func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)

QueryContext executes the query sql statement.

func (*DB) QueryRowContext added in v0.11.0

func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row

QueryRowContext executes the row query sql statement.

func (*DB) Select

func (db *DB) Select(column string, alias ...string) *SelectBuilder

Select returns a SELECT SQL builder.

func (*DB) SelectColumns added in v0.12.0

func (db *DB) SelectColumns(columns ...Column) *SelectBuilder

SelectColumns is equal to db.Select(columns[0].FullName()).Select(columns[1].FullName())...

func (*DB) SelectStruct added in v0.3.0

func (db *DB) SelectStruct(s interface{}, table ...string) *SelectBuilder

SelectStruct is equal to db.Select().SelectStruct(s, table...).

func (*DB) Selects added in v0.3.0

func (db *DB) Selects(columns ...string) *SelectBuilder

Selects is equal to db.Select(columns[0]).Select(columns[1])...

func (*DB) Update

func (db *DB) Update(table ...string) *UpdateBuilder

Update returns a UPDATE SQL builder.

type DeleteBuilder

type DeleteBuilder struct {
	ConditionSet
	// contains filtered or unexported fields
}

DeleteBuilder is used to build the DELETE statement.

Example
// No Where
delete1 := Delete().From("table")

// With Where
delete2 := Delete().From("table").
	Where(
		Equal("c1", "123"),
		IsNotNull("c2"),
	).
	Where(Less("c3", 123)).
	Where(
		Or(
			Like("c4", "%value%"),
			Between("c5", 100, 200),
		),
	)

sql1, args1 := delete1.Build()                      // Use the default dialect.
sql2, args2 := delete2.SetDialect(Postgres).Build() // Use the PostgreSQL dialect.

fmt.Println(sql1)
fmt.Println(args1)
fmt.Println(sql2)
fmt.Println(args2)
Output:
DELETE FROM `table`
[]
DELETE FROM "table" WHERE ("c1"=$1 AND "c2" IS NOT NULL AND "c3"<$2 AND ("c4" LIKE $3 OR "c5" BETWEEN $4 AND $5))
[123 123 %value% 100 200]

func Delete

func Delete(tables ...string) *DeleteBuilder

Delete is short for NewDeleteBuilder.

func NewDeleteBuilder

func NewDeleteBuilder(tables ...string) *DeleteBuilder

NewDeleteBuilder returns a new DELETE builder.

func (*DeleteBuilder) Build

func (b *DeleteBuilder) Build() (sql string, args []interface{})

Build builds the DELETE FROM TABLE sql statement.

func (*DeleteBuilder) Exec

func (b *DeleteBuilder) Exec() (sql.Result, error)

Exec builds the sql and executes it by *sql.DB.

func (*DeleteBuilder) ExecContext

func (b *DeleteBuilder) ExecContext(ctx context.Context) (sql.Result, error)

ExecContext builds the sql and executes it by *sql.DB.

func (*DeleteBuilder) From

func (b *DeleteBuilder) From(table string, alias ...string) *DeleteBuilder

From sets the table name from where to be deleted.

func (*DeleteBuilder) JoinFull added in v0.11.0

func (b *DeleteBuilder) JoinFull(table, alias string, ons ...JoinOn) *DeleteBuilder

JoinFull appends the "FULL JOIN table ON on..." statement.

func (*DeleteBuilder) JoinFullOuter added in v0.11.0

func (b *DeleteBuilder) JoinFullOuter(table, alias string, ons ...JoinOn) *DeleteBuilder

JoinFullOuter appends the "FULL OUTER JOIN table ON on..." statement.

func (*DeleteBuilder) JoinLeft added in v0.11.0

func (b *DeleteBuilder) JoinLeft(table, alias string, ons ...JoinOn) *DeleteBuilder

JoinLeft appends the "LEFT JOIN table ON on..." statement.

func (*DeleteBuilder) JoinLeftOuter added in v0.11.0

func (b *DeleteBuilder) JoinLeftOuter(table, alias string, ons ...JoinOn) *DeleteBuilder

JoinLeftOuter appends the "LEFT OUTER JOIN table ON on..." statement.

func (*DeleteBuilder) JoinRight added in v0.11.0

func (b *DeleteBuilder) JoinRight(table, alias string, ons ...JoinOn) *DeleteBuilder

JoinRight appends the "RIGHT JOIN table ON on..." statement.

func (*DeleteBuilder) JoinRightOuter added in v0.11.0

func (b *DeleteBuilder) JoinRightOuter(table, alias string, ons ...JoinOn) *DeleteBuilder

JoinRightOuter appends the "RIGHT OUTER JOIN table ON on..." statement.

func (*DeleteBuilder) SetDB

func (b *DeleteBuilder) SetDB(db *DB) *DeleteBuilder

SetDB sets the db.

func (*DeleteBuilder) SetDialect

func (b *DeleteBuilder) SetDialect(dialect Dialect) *DeleteBuilder

SetDialect resets the dialect.

func (*DeleteBuilder) SetExecutor added in v0.5.0

func (b *DeleteBuilder) SetExecutor(exec Executor) *DeleteBuilder

SetExecutor sets the executor to exec.

func (*DeleteBuilder) SetInterceptor

func (b *DeleteBuilder) SetInterceptor(f Interceptor) *DeleteBuilder

SetInterceptor sets the interceptor to f.

func (*DeleteBuilder) String

func (b *DeleteBuilder) String() string

String is the same as b.Build(), except args.

func (*DeleteBuilder) Table added in v0.11.0

func (b *DeleteBuilder) Table(table string) *DeleteBuilder

Table appends the table name to delete the rows from it.

func (*DeleteBuilder) Where

func (b *DeleteBuilder) Where(andConditions ...Condition) *DeleteBuilder

Where sets the WHERE conditions.

func (*DeleteBuilder) WhereNamedArgs added in v0.10.0

func (b *DeleteBuilder) WhereNamedArgs(args ...sql.NamedArg) *DeleteBuilder

WhereNamedArgs is the same as Where, but uses the NamedArg as the condition.

type Dialect

type Dialect interface {
	// Name returns the name of the dialect.
	Name() string

	// Placeholder returns the format of the ith argument,
	// such as "?" for MySQL and "$i" for PostgreSQL.
	//
	// Notice: i starts with 1.
	Placeholder(i int) string

	// Quote returns the quotation format of sql string,
	// such as `s` for MySQL and "s" for PostgreSQL.
	Quote(s string) string

	// LimitOffset returns the LIMIT OFFSET statement,
	// such as "LIMIT n" or "LIMIT n OFFSET m" for MySQL and PostgreSQL.
	LimitOffset(limit, offset int64) string
}

Dialect represents a dialect of the SQL.

var (
	MySQL    Dialect = dialect{mysqlDialect}
	Sqlite3  Dialect = dialect{sqlite3Dialect}
	Postgres Dialect = dialect{pqDialect}
)

Predefine some dialects.

func GetDialect

func GetDialect(name string) Dialect

GetDialect returns the dialect named name. Return nil instead if not exist.

type Executor added in v0.5.0

type Executor interface {
	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
}

Executor is used to execute the sql statement.

Example
package main

import (
	"context"
	"database/sql"
)

type noopExecutor struct{}

func (e noopExecutor) ExecContext(context.Context, string, ...interface{}) (sql.Result, error) {
	return nil, nil
}

func (e noopExecutor) QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) {
	return nil, nil
}

func (e noopExecutor) QueryRowContext(context.Context, string, ...interface{}) *sql.Row {
	return nil
}

func main() {
	db := DB{Dialect: MySQL}
	db.Executor = noopExecutor{} // It should be db.DB, but we use noopExecutor for test.
	db.Insert().Into("table").Columns("c1", "c2", "c3").Values("v1", "v2", "v3").Exec()
	db.Update().Table("table").Set(Assign("c1", "n1")).Where(Equal("c2", "v2")).Exec()
	db.Selects("c1", "c2", "c3").From("table").Query()
	db.Delete().From("table").Where(Equal("c3", "v3"))
}

type InsertBuilder

type InsertBuilder struct {
	// contains filtered or unexported fields
}

InsertBuilder is used to build the INSERT statement.

Example
// Single Value
insert1 := Insert().Into("table").Columns("c1", "c2", "c3").
	Values("v1", "v2", "v3")

// Many Values
insert2 := Insert().Into("table").Columns("c1", "c2", "c3").
	Values("v1", "v2", "v3").
	Values("v4", "v5", "v6").
	Values("v7", "v8", "v9")

// No Value, which will build a single value placeholder.
insert3 := Insert().Into("table").Columns("c1", "c2", "c3")

// No Column
insert4 := Insert().Into("table").Values("v1", "v2", "v3")
insert5 := Insert().Into("table").Values("v11", "v12").Values("v21", "v22")

sql1, args1 := insert1.SetDialect(Postgres).Build() // Use the PostgreSQL dialect.
sql2, args2 := insert2.SetDialect(Postgres).Build() // Use the PostgreSQL dialect.
sql3, args3 := insert3.Build()                      // Use the default dialect.
sql4, args4 := insert4.Build()                      // Use the default dialect.
sql5, args5 := insert5.Build()                      // Use the default dialect.

fmt.Println(sql1)
fmt.Println(args1)

fmt.Println(sql2)
fmt.Println(args2)

fmt.Println(sql3)
fmt.Println(args3)

fmt.Println(sql4)
fmt.Println(args4)

fmt.Println(sql5)
fmt.Println(args5)
Output:
INSERT INTO "table" ("c1", "c2", "c3") VALUES ($1, $2, $3)
[v1 v2 v3]
INSERT INTO "table" ("c1", "c2", "c3") VALUES ($1, $2, $3), ($4, $5, $6), ($7, $8, $9)
[v1 v2 v3 v4 v5 v6 v7 v8 v9]
INSERT INTO `table` (`c1`, `c2`, `c3`) VALUES (?, ?, ?)
[]
INSERT INTO `table` VALUES (?, ?, ?)
[v1 v2 v3]
INSERT INTO `table` VALUES (?, ?), (?, ?)
[v11 v12 v21 v22]

func Insert

func Insert() *InsertBuilder

Insert is short for NewInsertBuilder.

func NewInsertBuilder

func NewInsertBuilder() *InsertBuilder

NewInsertBuilder returns a new INSERT builder.

func (*InsertBuilder) Build

func (b *InsertBuilder) Build() (sql string, args []interface{})

Build builds the INSERT INTO TABLE sql statement.

func (*InsertBuilder) ColumnValues added in v0.12.0

func (b *InsertBuilder) ColumnValues(columns ...Column) *InsertBuilder

ColumnValues is the same as Values. But it will set it if the columns are not set. Or it will check whether the columns are consistent.

func (*InsertBuilder) Columns

func (b *InsertBuilder) Columns(columns ...string) *InsertBuilder

Columns sets the inserted columns.

func (*InsertBuilder) Exec

func (b *InsertBuilder) Exec() (sql.Result, error)

Exec builds the sql and executes it by *sql.DB.

func (*InsertBuilder) ExecContext

func (b *InsertBuilder) ExecContext(ctx context.Context) (sql.Result, error)

ExecContext builds the sql and executes it by *sql.DB.

func (*InsertBuilder) IgnoreInto

func (b *InsertBuilder) IgnoreInto(table string) *InsertBuilder

IgnoreInto sets the table name with "INSERT IGNORE INTO".

func (*InsertBuilder) Into

func (b *InsertBuilder) Into(table string) *InsertBuilder

Into sets the table name with "INSERT INTO".

func (*InsertBuilder) NamedValues

func (b *InsertBuilder) NamedValues(values ...sql.NamedArg) *InsertBuilder

NamedValues is the same as Values. But it will set it if the columns are not set.

DEPRECATED!!!

Example
v1 := sql.Named("column1", "value1")
v2 := sql.Named("column2", "value2")
v3 := sql.Named("column3", "value3")

insert := Insert().Into("table").NamedValues(v1, v2, v3)
sql, args := insert.Build()

fmt.Println(sql)
fmt.Println(args)
Output:
INSERT INTO `table` (`column1`, `column2`, `column3`) VALUES (?, ?, ?)
[value1 value2 value3]

func (*InsertBuilder) ReplaceInto

func (b *InsertBuilder) ReplaceInto(table string) *InsertBuilder

ReplaceInto sets the table name with "REPLACE INTO".

REPLACE INTO is a MySQL extension to the SQL standard.

func (*InsertBuilder) SetDB

func (b *InsertBuilder) SetDB(db *DB) *InsertBuilder

SetDB sets the db.

func (*InsertBuilder) SetDialect

func (b *InsertBuilder) SetDialect(dialect Dialect) *InsertBuilder

SetDialect resets the dialect.

func (*InsertBuilder) SetExecutor added in v0.5.0

func (b *InsertBuilder) SetExecutor(exec Executor) *InsertBuilder

SetExecutor sets the executor to exec.

func (*InsertBuilder) SetInterceptor

func (b *InsertBuilder) SetInterceptor(f Interceptor) *InsertBuilder

SetInterceptor sets the interceptor to f.

func (*InsertBuilder) String

func (b *InsertBuilder) String() string

String is the same as b.Build(), except args.

func (*InsertBuilder) Struct added in v0.3.0

func (b *InsertBuilder) Struct(s interface{}) *InsertBuilder

Struct is the same as NamedValues, but extracts the fields of the struct as the named values to be inserted, which supports the tag named "sql" to modify the column name.

  1. If the value of the tag is "-", however, the field will be ignored.
  2. If the tag value contains "omitempty", the ZERO field will be ignored.
  3. If the tag contains the attribute "notpropagate", for the embeded struct, do not scan the fields of the embeded struct.
Example
type S struct {
	DefaultField  string
	ModifiedField string `sql:"field"`
	ZeroField     string `sql:",omitempty"`
	IgnoredField  string `sql:"-"`
}

s := S{DefaultField: "v1", IgnoredField: "v2"}
insert := Insert().Into("table").Struct(s)
sql, args := insert.Build()

fmt.Println(sql)
fmt.Println(args)
Output:
INSERT INTO `table` (`DefaultField`, `field`) VALUES (?, ?)
[v1 ]

func (*InsertBuilder) Values

func (b *InsertBuilder) Values(values ...interface{}) *InsertBuilder

Values appends the inserting values.

type Interceptor

type Interceptor func(sql string, args []interface{}) (string, []interface{})

Interceptor is used to intercept the built sql result and return a new one.

func LogInterceptor added in v0.7.0

func LogInterceptor(logf func(string, ...interface{}), logArgs ...bool) Interceptor

LogInterceptor returns a interceptor to log the sql and args.

type JoinOn added in v0.11.0

type JoinOn struct {
	Left  string
	Right string
}

JoinOn is the join on statement.

func On added in v0.11.0

func On(left, right string) JoinOn

On returns a JoinOn instance.

type Opener added in v0.21.0

type Opener func(driverName, dataSourceName string) (*sql.DB, error)

Opener is used to open a *sql.DB.

var DefaultOpener Opener = sql.Open

DefaultOpener is used to open a *sql.DB.

type Order

type Order string

Order represents the order used by ORDER BY.

const (
	Asc  Order = "ASC"
	Desc Order = "DESC"
)

Predefine some orders used by ORDER BY.

type Row added in v0.3.0

type Row struct {
	Columns []string // Only used by ScanStruct
	*sql.Row
}

Row is used to wrap sql.Row.

func NewRow added in v0.23.1

func NewRow(row *sql.Row, columns ...string) Row

NewRow returns a new Row.

func (Row) Scan added in v0.18.0

func (r Row) Scan(dests ...interface{}) (err error)

Scan implements the interface sql.Scanner, which is the proxy of sql.Row and supports that the sql value is NULL.

func (Row) ScanStruct added in v0.3.0

func (r Row) ScanStruct(s interface{}) (err error)

ScanStruct is the same as Scan, but the columns are scanned into the struct s, which uses ScanColumnsToStruct.

func (Row) ScanStructWithColumns added in v0.22.0

func (r Row) ScanStructWithColumns(s interface{}, columns ...string) (err error)

ScanStructWithColumns is the same as Scan, but the columns are scanned into the struct s by using ScanColumnsToStruct.

type Rows added in v0.3.0

type Rows struct {
	Columns []string // Only used by ScanStruct
	*sql.Rows
}

Rows is used to wrap sql.Rows.

func NewRows added in v0.23.1

func NewRows(rows *sql.Rows, columns ...string) Rows

NewRows returns a new Rows.

func (Rows) Scan added in v0.18.0

func (r Rows) Scan(dests ...interface{}) (err error)

Scan implements the interface sql.Scanner, which is the proxy of sql.Rows and supports that the sql value is NULL.

func (Rows) ScanSlice added in v0.10.0

func (r Rows) ScanSlice(slice interface{}) (err error)

ScanSlice is used to scan the row set into the slice.

func (Rows) ScanStruct added in v0.3.0

func (r Rows) ScanStruct(s interface{}) (err error)

ScanStruct is the same as Scan, but the columns are scanned into the struct s, which uses ScanColumnsToStruct.

func (Rows) ScanStructWithColumns added in v0.22.0

func (r Rows) ScanStructWithColumns(s interface{}, columns ...string) (err error)

ScanStructWithColumns is the same as Scan, but the columns are scanned into the struct s by using ScanColumnsToStruct.

type SelectBuilder

type SelectBuilder struct {
	ConditionSet
	// contains filtered or unexported fields
}

SelectBuilder is used to build the SELECT statement.

Example
sel1 := Select("*").From("table").Where(Equal("id", 123))
sel2 := Select("*").From("table", "alias").Where(Equal("id", 123))
sel3 := Select("id", "c1").Select("name", "c2").From("table", "alias").Where(Equal("id", 123))
sel4 := Select("A.id").Select("B.name").From("table1", "A").From("table2", "B").Where(ColumnEqual("A.id", "B.id"))

sql1, args1 := sel1.Build()
sql2, args2 := sel2.Build()
sql3, args3 := sel3.Build()
sql4, args4 := sel4.Build()

fmt.Println(sql1)
fmt.Println(args1)

fmt.Println(sql2)
fmt.Println(args2)

fmt.Println(sql3)
fmt.Println(args3)

fmt.Println(sql4)
fmt.Println(args4)
Output:
SELECT * FROM `table` WHERE `id`=?
[123]
SELECT * FROM `table` AS `alias` WHERE `id`=?
[123]
SELECT `id` AS `c1`, `name` AS `c2` FROM `table` AS `alias` WHERE `id`=?
[123]
SELECT `A`.`id`, `B`.`name` FROM `table1` AS `A`, `table2` AS `B` WHERE `A`.`id`=`B`.`id`
[]

func NewSelectBuilder

func NewSelectBuilder(column string, alias ...string) *SelectBuilder

NewSelectBuilder returns a new SELECT builder.

func Select

func Select(column string, alias ...string) *SelectBuilder

Select is short for NewSelectBuilder.

func SelectColumns added in v0.12.0

func SelectColumns(columns ...Column) *SelectBuilder

SelectColumns is equal to Select(columns[0].FullName()).Select(columns[1].FullName())...

func SelectStruct added in v0.3.0

func SelectStruct(s interface{}, table ...string) *SelectBuilder

SelectStruct is equal to Select().SelectStruct(s, table...).

func Selects added in v0.3.0

func Selects(columns ...string) *SelectBuilder

Selects is equal to Select(columns[0]).Select(columns[1])...

func (*SelectBuilder) BindRow added in v0.12.0

func (b *SelectBuilder) BindRow(dest ...interface{}) error

BindRow is equal to b.BindRowContext(context.Background(), dest...).

func (*SelectBuilder) BindRowContext added in v0.12.0

func (b *SelectBuilder) BindRowContext(c context.Context, dest ...interface{}) error

BindRowContext is convenient function, which is equal to b.QueryRowContext(c).Scan(dest...).

func (*SelectBuilder) BindRowStruct added in v0.12.0

func (b *SelectBuilder) BindRowStruct(dest interface{}) error

BindRowStruct is equal to b.BindRowStructContext(context.Background(), dest).

func (*SelectBuilder) BindRowStructContext added in v0.12.0

func (b *SelectBuilder) BindRowStructContext(c context.Context, dest interface{}) error

BindRowStructContext is convenient function, which is equal to b.QueryRowContext(c).ScanStruct(dest).

func (*SelectBuilder) BindRows added in v0.10.0

func (b *SelectBuilder) BindRows(slice interface{}) error

BindRows is equal to b.BindRowsContext(context.Background(), slice).

func (*SelectBuilder) BindRowsContext added in v0.10.0

func (b *SelectBuilder) BindRowsContext(ctx context.Context, slice interface{}) error

BindRowsContext is the same QueryContext, but scans the result set into the slice.

Notice: slice must be a pointer to a slice. And the element of the slice may be a struct or type implemented the interface sql.Scanner.

func (*SelectBuilder) Build

func (b *SelectBuilder) Build() (sql string, args []interface{})

Build builds the SELECT sql statement.

func (*SelectBuilder) Distinct

func (b *SelectBuilder) Distinct() *SelectBuilder

Distinct marks SELECT as DISTINCT.

func (*SelectBuilder) From

func (b *SelectBuilder) From(table string, alias ...string) *SelectBuilder

From sets table name in SELECT.

func (*SelectBuilder) FromTable added in v0.19.0

func (b *SelectBuilder) FromTable(table Table, alias ...string) *SelectBuilder

FromTable is equal to b.From(table.Name, alias...).

func (*SelectBuilder) FromTables added in v0.19.0

func (b *SelectBuilder) FromTables(tables ...Table) *SelectBuilder

FromTables is the same as b.FromTable(table0).FromTable(table1)...

func (*SelectBuilder) Froms added in v0.19.0

func (b *SelectBuilder) Froms(tables ...string) *SelectBuilder

Froms is the same as b.From(table0).From(table1)...

func (*SelectBuilder) GetExecutor added in v0.23.0

func (b *SelectBuilder) GetExecutor() Executor

GetExecutor returns the sql executor.

func (*SelectBuilder) GroupBy

func (b *SelectBuilder) GroupBy(columns ...string) *SelectBuilder

GroupBy resets the GROUP BY columns.

Example
s := Select("*").From("table").Where(Equal("id", 123)).GroupBy("area")
sql, args := s.Build()

fmt.Println(sql)
fmt.Println(args)
Output:
SELECT * FROM `table` WHERE `id`=? GROUP BY `area`
[123]

func (*SelectBuilder) Having

func (b *SelectBuilder) Having(exprs ...string) *SelectBuilder

Having appends the HAVING expression.

func (*SelectBuilder) Join

func (b *SelectBuilder) Join(table, alias string, ons ...JoinOn) *SelectBuilder

Join appends the "JOIN table ON on..." statement.

Example
s := Select("*").From("table1").Join("table2", "", On("table1.id", "table2.id")).
	Where(Equal("table1.id", 123)).OrderByAsc("table1.time").Limit(10).Offset(100)
sql, args := s.Build()

fmt.Println(sql)
fmt.Println(args)
Output:
SELECT * FROM `table1` JOIN `table2` ON `table1`.`id`=`table2`.`id` WHERE `table1`.`id`=? ORDER BY `table1`.`time` ASC LIMIT 10 OFFSET 100
[123]

func (*SelectBuilder) JoinFull

func (b *SelectBuilder) JoinFull(table, alias string, ons ...JoinOn) *SelectBuilder

JoinFull appends the "FULL JOIN table ON on..." statement.

func (*SelectBuilder) JoinFullOuter

func (b *SelectBuilder) JoinFullOuter(table, alias string, ons ...JoinOn) *SelectBuilder

JoinFullOuter appends the "FULL OUTER JOIN table ON on..." statement.

func (*SelectBuilder) JoinLeft

func (b *SelectBuilder) JoinLeft(table, alias string, ons ...JoinOn) *SelectBuilder

JoinLeft appends the "LEFT JOIN table ON on..." statement.

func (*SelectBuilder) JoinLeftOuter

func (b *SelectBuilder) JoinLeftOuter(table, alias string, ons ...JoinOn) *SelectBuilder

JoinLeftOuter appends the "LEFT OUTER JOIN table ON on..." statement.

func (*SelectBuilder) JoinRight

func (b *SelectBuilder) JoinRight(table, alias string, ons ...JoinOn) *SelectBuilder

JoinRight appends the "RIGHT JOIN table ON on..." statement.

func (*SelectBuilder) JoinRightOuter

func (b *SelectBuilder) JoinRightOuter(table, alias string, ons ...JoinOn) *SelectBuilder

JoinRightOuter appends the "RIGHT OUTER JOIN table ON on..." statement.

func (*SelectBuilder) Limit

func (b *SelectBuilder) Limit(limit int64) *SelectBuilder

Limit sets the LIMIT to limit.

Example
s := Select("*").From("table").Where(Equal("id", 123)).
	OrderByAsc("time").Limit(10).Offset(100)
sql, args := s.Build()

fmt.Println(sql)
fmt.Println(args)
Output:
SELECT * FROM `table` WHERE `id`=? ORDER BY `time` ASC LIMIT 10 OFFSET 100
[123]

func (*SelectBuilder) Offset

func (b *SelectBuilder) Offset(offset int64) *SelectBuilder

Offset sets the OFFSET to offset.

func (*SelectBuilder) OrderBy

func (b *SelectBuilder) OrderBy(column string, order Order) *SelectBuilder

OrderBy appends the column used by ORDER BY.

Example
s1 := Select("*").From("table").Where(Equal("id", 123)).OrderBy("time", Asc)
s2 := Select("*").From("table").Where(Equal("id", 123)).OrderBy("time", Desc)

sql1, args1 := s1.Build()
sql2, args2 := s2.Build()

fmt.Println(sql1)
fmt.Println(args1)

fmt.Println(sql2)
fmt.Println(args2)
Output:
SELECT * FROM `table` WHERE `id`=? ORDER BY `time` ASC
[123]
SELECT * FROM `table` WHERE `id`=? ORDER BY `time` DESC
[123]

func (*SelectBuilder) OrderByAsc added in v0.10.0

func (b *SelectBuilder) OrderByAsc(column string) *SelectBuilder

OrderByAsc appends the column used by ORDER BY ASC.

func (*SelectBuilder) OrderByDesc added in v0.10.0

func (b *SelectBuilder) OrderByDesc(column string) *SelectBuilder

OrderByDesc appends the column used by ORDER BY DESC.

func (*SelectBuilder) Paginate added in v0.3.0

func (b *SelectBuilder) Paginate(pageNum, pageSize int64) *SelectBuilder

Paginate is equal to Limit(pageSize).Offset(pageNum * pageSize).

Notice: pageNum starts with 0.

func (*SelectBuilder) Query

func (b *SelectBuilder) Query() (Rows, error)

Query builds the sql and executes it.

func (*SelectBuilder) QueryContext

func (b *SelectBuilder) QueryContext(ctx context.Context) (Rows, error)

QueryContext builds the sql and executes it.

func (*SelectBuilder) QueryRow

func (b *SelectBuilder) QueryRow() Row

QueryRow builds the sql and executes it.

func (*SelectBuilder) QueryRowContext

func (b *SelectBuilder) QueryRowContext(ctx context.Context) Row

QueryRowContext builds the sql and executes it.

func (*SelectBuilder) Select

func (b *SelectBuilder) Select(column string, alias ...string) *SelectBuilder

Select appends the selected column in SELECT.

func (*SelectBuilder) SelectColumns added in v0.12.0

func (b *SelectBuilder) SelectColumns(columns ...Column) *SelectBuilder

SelectColumns is equal to b.Select(columns[0].FullName()).Select(columns[1].FullName())...

func (*SelectBuilder) SelectStruct added in v0.3.0

func (b *SelectBuilder) SelectStruct(s interface{}, table ...string) *SelectBuilder

SelectStruct reflects and extracts the fields of the struct as the selected columns, which supports the tag named "sql" to modify the column name.

If the value of the tag is "-", however, the field will be ignored. If the tag contains the attribute "notpropagate", for the embeded struct, do not scan the fields of the embeded struct.

Example
type S struct {
	DefaultField  string
	ModifiedField string `sql:"field"`
	IgnoredField  string `sql:"-"`
}

s := S{}
sb := SelectStruct(s, "A")
columns := sb.SelectedColumns()
fmt.Println(columns)

err := ScanColumnsToStruct(func(values ...interface{}) error {
	for i, v := range values {
		vp := v.(*string)
		switch i {
		case 0:
			*vp = "a"
		case 1:
			*vp = "b"
		default:
			fmt.Printf("unknown %dth column value\n", i)
		}
	}
	return nil
}, columns, &s)

if err != nil {
	fmt.Println(err)
} else {
	fmt.Println(s.DefaultField)
	fmt.Println(s.ModifiedField)
	fmt.Println(s.IgnoredField)
}
Output:
[DefaultField field]
a
b

func (*SelectBuilder) SelectedColumns added in v0.3.0

func (b *SelectBuilder) SelectedColumns() []string

SelectedColumns is the same as SelectedFullColumns, but returns the short names instead.

func (*SelectBuilder) SelectedFullColumns added in v0.22.0

func (b *SelectBuilder) SelectedFullColumns() []string

SelectedFullColumns returns the full names of the selected columns.

Notice: if the column has the alias, the alias will be returned instead.

func (*SelectBuilder) Selects added in v0.3.0

func (b *SelectBuilder) Selects(columns ...string) *SelectBuilder

Selects is equal to b.Select(columns[0]).Select(columns[1])...

func (*SelectBuilder) SetDB

func (b *SelectBuilder) SetDB(db *DB) *SelectBuilder

SetDB sets the db.

func (*SelectBuilder) SetDialect

func (b *SelectBuilder) SetDialect(dialect Dialect) *SelectBuilder

SetDialect resets the dialect.

func (*SelectBuilder) SetExecutor added in v0.5.0

func (b *SelectBuilder) SetExecutor(exec Executor) *SelectBuilder

SetExecutor sets the executor to exec.

func (*SelectBuilder) SetInterceptor

func (b *SelectBuilder) SetInterceptor(f Interceptor) *SelectBuilder

SetInterceptor sets the interceptor to f.

func (*SelectBuilder) String

func (b *SelectBuilder) String() string

String is the same as b.Build(), except args.

func (*SelectBuilder) Where

func (b *SelectBuilder) Where(andConditions ...Condition) *SelectBuilder

Where sets the WHERE conditions.

func (*SelectBuilder) WhereNamedArgs added in v0.10.0

func (b *SelectBuilder) WhereNamedArgs(args ...sql.NamedArg) *SelectBuilder

WhereNamedArgs is the same as Where, but uses the NamedArg as the condition.

type Setter

type Setter interface {
	BuildSetter(*ArgsBuilder) string
}

Setter is the setter interface by Update.

type SetterSet added in v0.10.0

type SetterSet struct{}

SetterSet collects some UPDATE setters together.

func (SetterSet) Add added in v0.10.0

func (s SetterSet) Add(column string, value interface{}) ColumnSetter

Add is a proxy of Add.

func (SetterSet) Assign added in v0.10.0

func (s SetterSet) Assign(column string, value interface{}) ColumnSetter

Assign is a proxy of Assign.

func (SetterSet) Dec added in v0.12.0

func (s SetterSet) Dec(column string) ColumnSetter

Dec is a proxy of Dec.

func (SetterSet) Div added in v0.10.0

func (s SetterSet) Div(column string, value interface{}) ColumnSetter

Div is a proxy of Div.

func (SetterSet) Inc added in v0.12.0

func (s SetterSet) Inc(column string) ColumnSetter

Inc is a proxy of Inc.

func (SetterSet) Mul added in v0.10.0

func (s SetterSet) Mul(column string, value interface{}) ColumnSetter

Mul is a proxy of Mul.

func (SetterSet) Set added in v0.10.0

func (s SetterSet) Set(column string, value interface{}) ColumnSetter

Set is the alias of Assign.

func (SetterSet) Sub added in v0.10.0

func (s SetterSet) Sub(column string, value interface{}) ColumnSetter

Sub is a proxy Sub.

type Table

type Table struct {
	Name string
	*DB
}

Table represents a SQL table.

func NewTable added in v0.14.0

func NewTable(name string) Table

NewTable returns a new Table with the name.

func (Table) CreateTable added in v0.17.0

func (t Table) CreateTable() *TableBuilder

CreateTable returns a table builder.

func (Table) DeleteFrom added in v0.17.0

func (t Table) DeleteFrom(conds ...Condition) *DeleteBuilder

DeleteFrom returns a DELETE FROM builder.

func (Table) GetDB added in v0.17.0

func (t Table) GetDB() *DB

GetDB returns the set DB. Or returns DefaultDB instead if not set.

func (Table) InsertInto added in v0.17.0

func (t Table) InsertInto() *InsertBuilder

InsertInto returns a INSERT INTO builder.

func (Table) NewColumn added in v0.17.0

func (t Table) NewColumn(colName string) Column

NewColumn returns a new Column with the table name and the column name.

func (Table) Select added in v0.17.0

func (t Table) Select(column string, alias ...string) *SelectBuilder

Select returns a SELECT FROM builder.

func (Table) SelectColumns added in v0.17.0

func (t Table) SelectColumns(columns ...Column) *SelectBuilder

SelectColumns returns a SELECT FROM builder.

func (Table) SelectStruct added in v0.17.0

func (t Table) SelectStruct(s interface{}, table ...string) *SelectBuilder

SelectStruct returns a SELECT FROM builder.

func (Table) Selects added in v0.17.0

func (t Table) Selects(columns ...string) *SelectBuilder

Selects returns a SELECT FROM builder.

func (*Table) SetDB added in v0.23.0

func (t *Table) SetDB(db *DB)

SetDB reset the db.

func (Table) Update added in v0.17.0

func (t Table) Update(setters ...Setter) *UpdateBuilder

Update returns a UPDATE builder.

func (Table) WithDB added in v0.17.0

func (t Table) WithDB(db *DB) Table

WithDB returns a new Table with the given db.

type TableBuilder

type TableBuilder struct {
	// contains filtered or unexported fields
}

TableBuilder is used to build the CREATE TABLE statement.

Example
table := NewTableBuilder("table").IfNotExist().
	Define("id", "BIGINT", "PRIMARY KEY", "AUTO_INCREMENT").
	Define("name", "VARCHAR(255)", "NOT NULL", `COMMENT "user name"`).
	Define("age", "INTEGER", "NOT NULL", "DEFAULT", 123).
	Option("ENGINE=InnoDB", "DEFAULT CHARSET=utf8mb4")

fmt.Println(table.String())
Output:
CREATE TABLE IF NOT EXISTS `table` (
    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
    `name` VARCHAR(255) NOT NULL COMMENT "user name",
    `age` INTEGER NOT NULL DEFAULT 123
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

func NewTableBuilder

func NewTableBuilder(table string) *TableBuilder

NewTableBuilder returns a new CREATE TABLE builder.

func (*TableBuilder) Build

func (b *TableBuilder) Build() (sql string, args []interface{})

Build builds the CREATE TABLE sql statement.

func (*TableBuilder) Define

func (b *TableBuilder) Define(colName, colType string, colOpts ...interface{}) *TableBuilder

Define adds definition of a column or index in CREATE TABLE.

func (*TableBuilder) Exec

func (b *TableBuilder) Exec() (sql.Result, error)

Exec builds the sql and executes it by *sql.DB.

func (*TableBuilder) ExecContext

func (b *TableBuilder) ExecContext(ctx context.Context) (sql.Result, error)

ExecContext builds the sql and executes it by *sql.DB.

func (*TableBuilder) IfNotExist

func (b *TableBuilder) IfNotExist() *TableBuilder

IfNotExist adds the setting "IF NOT EXISTS".

func (*TableBuilder) Option

func (b *TableBuilder) Option(options ...string) *TableBuilder

Option adds a table option in CREATE TABLE.

func (*TableBuilder) SetDB

func (b *TableBuilder) SetDB(db *DB) *TableBuilder

SetDB sets the db.

func (*TableBuilder) SetDialect

func (b *TableBuilder) SetDialect(dialect Dialect) *TableBuilder

SetDialect resets the dialect.

func (*TableBuilder) SetExecutor added in v0.5.0

func (b *TableBuilder) SetExecutor(exec Executor) *TableBuilder

SetExecutor sets the executor to exec.

func (*TableBuilder) SetInterceptor

func (b *TableBuilder) SetInterceptor(f Interceptor) *TableBuilder

SetInterceptor sets the interceptor to f.

func (*TableBuilder) String

func (b *TableBuilder) String() string

String is the same as b.Build(), except args.

func (*TableBuilder) Temporary

func (b *TableBuilder) Temporary() *TableBuilder

Temporary creates the Temporary table, that's, CREATE TEMPORARY TABLE.

type Time added in v0.9.0

type Time struct {
	Layout string // If empty, use defaults.TimeFormat instead when formatting time.
	time.Time
}

Time is used to read/write the time.Time from/to DB.

func Now added in v0.9.0

func Now() Time

Now returns the current Time.

func (Time) MarshalJSON added in v0.14.0

func (t Time) MarshalJSON() ([]byte, error)

MarshalJSON implements the interface json.Marshaler.

func (*Time) Scan added in v0.9.0

func (t *Time) Scan(src interface{}) (err error)

Scan implements the interface sql.Scanner.

func (*Time) SetFormat added in v0.22.3

func (t *Time) SetFormat(layout string)

SetFormat sets the format layout.

func (Time) String added in v0.14.0

func (t Time) String() string

func (Time) Value added in v0.9.0

func (t Time) Value() (driver.Value, error)

Value implements the interface driver.Valuer.

type UpdateBuilder

type UpdateBuilder struct {
	SetterSet
	ConditionSet
	// contains filtered or unexported fields
}

UpdateBuilder is used to build the UPDATE statement.

Example
// No Where
update1 := Update().Table("table").Set(Assign("c1", "v1"), Inc("c2")).
	Set(Assign("c3", 123), Add("c4", 456))

// With Where
update2 := Update().Table("table").Set(Assign("c1", "v1")).Set(Dec("c2")).
	Where(Equal("c3", 789))

sql1, args1 := update1.Build()
sql2, args2 := update2.SetDialect(Postgres).Build()

fmt.Println(sql1)
fmt.Println(args1)
fmt.Println(sql2)
fmt.Println(args2)
Output:
UPDATE `table` SET `c1`=?, `c2`=`c2`+1, `c3`=?, `c4`=`c4`+?
[v1 123 456]
UPDATE "table" SET "c1"=$1, "c2"="c2"-1 WHERE "c3"=$2
[v1 789]

func NewUpdateBuilder

func NewUpdateBuilder(table ...string) *UpdateBuilder

NewUpdateBuilder returns a new UPDATE builder.

func Update

func Update(table ...string) *UpdateBuilder

Update is short for NewUpdateBuilder.

func (*UpdateBuilder) Build

func (b *UpdateBuilder) Build() (sql string, args []interface{})

Build builds the UPDATE sql statement.

func (*UpdateBuilder) Exec

func (b *UpdateBuilder) Exec() (sql.Result, error)

Exec builds the sql and executes it by *sql.DB.

func (*UpdateBuilder) ExecContext

func (b *UpdateBuilder) ExecContext(ctx context.Context) (sql.Result, error)

ExecContext builds the sql and executes it by *sql.DB.

func (*UpdateBuilder) From added in v0.11.0

func (b *UpdateBuilder) From(table string, alias ...string) *UpdateBuilder

From appends the from table name.

func (*UpdateBuilder) JoinFull added in v0.11.0

func (b *UpdateBuilder) JoinFull(table, alias string, ons ...JoinOn) *UpdateBuilder

JoinFull appends the "FULL JOIN table ON on..." statement.

func (*UpdateBuilder) JoinFullOuter added in v0.11.0

func (b *UpdateBuilder) JoinFullOuter(table, alias string, ons ...JoinOn) *UpdateBuilder

JoinFullOuter appends the "FULL OUTER JOIN table ON on..." statement.

func (*UpdateBuilder) JoinLeft added in v0.11.0

func (b *UpdateBuilder) JoinLeft(table, alias string, ons ...JoinOn) *UpdateBuilder

JoinLeft appends the "LEFT JOIN table ON on..." statement.

func (*UpdateBuilder) JoinLeftOuter added in v0.11.0

func (b *UpdateBuilder) JoinLeftOuter(table, alias string, ons ...JoinOn) *UpdateBuilder

JoinLeftOuter appends the "LEFT OUTER JOIN table ON on..." statement.

func (*UpdateBuilder) JoinRight added in v0.11.0

func (b *UpdateBuilder) JoinRight(table, alias string, ons ...JoinOn) *UpdateBuilder

JoinRight appends the "RIGHT JOIN table ON on..." statement.

func (*UpdateBuilder) JoinRightOuter added in v0.11.0

func (b *UpdateBuilder) JoinRightOuter(table, alias string, ons ...JoinOn) *UpdateBuilder

JoinRightOuter appends the "RIGHT OUTER JOIN table ON on..." statement.

func (*UpdateBuilder) Set

func (b *UpdateBuilder) Set(setters ...Setter) *UpdateBuilder

Set appends the SET statement to setters.

func (*UpdateBuilder) SetDB

func (b *UpdateBuilder) SetDB(db *DB) *UpdateBuilder

SetDB sets the DB to db.

func (*UpdateBuilder) SetDialect

func (b *UpdateBuilder) SetDialect(dialect Dialect) *UpdateBuilder

SetDialect resets the dialect.

func (*UpdateBuilder) SetExecutor added in v0.5.0

func (b *UpdateBuilder) SetExecutor(exec Executor) *UpdateBuilder

SetExecutor sets the executor to exec.

func (*UpdateBuilder) SetInterceptor

func (b *UpdateBuilder) SetInterceptor(f Interceptor) *UpdateBuilder

SetInterceptor sets the interceptor to f.

func (*UpdateBuilder) SetNamedArg added in v0.10.0

func (b *UpdateBuilder) SetNamedArg(args ...sql.NamedArg) *UpdateBuilder

SetNamedArg is the same as Set, but uses the NamedArg as the Setter.

func (*UpdateBuilder) String

func (b *UpdateBuilder) String() string

String is the same as b.Build(), except args.

func (*UpdateBuilder) Table

func (b *UpdateBuilder) Table(table string, alias ...string) *UpdateBuilder

Table appends the table name.

func (*UpdateBuilder) Where

func (b *UpdateBuilder) Where(andConditions ...Condition) *UpdateBuilder

Where appends the WHERE conditions.

func (*UpdateBuilder) WhereNamedArgs added in v0.10.0

func (b *UpdateBuilder) WhereNamedArgs(args ...sql.NamedArg) *UpdateBuilder

WhereNamedArgs is the same as Where, but uses the NamedArg as the condition.

Jump to

Keyboard shortcuts

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