sqlbuilder
packagemoduleThis package is not in the latest version of its module.
Details
Validgo.mod file
The Go module system was introduced in Go 1.11 and is the official dependency management solution for Go.
Redistributable license
Redistributable licenses place minimal restrictions on how software can be used, modified, and redistributed.
Tagged version
Modules with tagged versions give importers more predictable builds.
Stable version
When a project reaches major version v1 it is considered stable.
- Learn more about best practices
Repository
Links
README¶
SQL builder for Go
- Install
- Usage
- Basic usage
- Pre-defined SQL builders
- Build
WHEREclause - Share
WHEREclause among builders - Build
ORDER BYclause - Build SQL for different systems
- Using
Structas a light weight ORM - Nested SQL
- Nested
JOIN - Use
sql.Namedin a builder - Argument modifiers
- Freestyle builder
- Clone builders
- Using special syntax to build SQL
- Interpolate
argsin thesql
- License
Thesqlbuilder package offers a comprehensive suite of SQL string concatenation utilities. It is designed to facilitate the construction of SQL statements compatible with Go's standard librarysql.DB andsql.Stmt interfaces, focusing on optimizing the performance of SQL statement creation and minimizing memory usage.
The primary objective of this package's design was to craft a SQL construction library that operates independently of specific database drivers and business logic. It is tailored to accommodate the diverse needs of enterprise environments, including the use of custom database drivers, adherence to specialized operational standards, integration into heterogeneous systems, and handling of non-standard SQL in intricate scenarios. Following its open-source release, the package has undergone extensive testing within a large-scale enterprise context, successfully managing the workload of hundreds of millions of orders daily and nearly ten million transactions daily, thus highlighting its robust performance and scalability.
This package is not restricted to any particular database driver and does not automatically establish connections with any database systems. It does not presuppose the execution of the generated SQL, making it versatile for a broad spectrum of application scenarios that involve the construction of SQL-like statements. It is equally well-suited for further development aimed at creating more business-specific database interaction packages, ORMs, and similar tools.
Install
Install this package by executing the following command:
go get github.com/huandu/go-sqlbuilderUsage
Basic usage
We can rapidly construct SQL statements using this package.
sql := sqlbuilder.Select("id", "name").From("demo.user"). Where("status = 1").Limit(10). String()fmt.Println(sql)// Output:// SELECT id, name FROM demo.user WHERE status = 1 LIMIT 10In common scenarios, it is necessary to escape all user inputs. To achieve this, initialize a builder at the outset.
sb := sqlbuilder.NewSelectBuilder()sb.Select("id", "name", sb.As("COUNT(*)", "c"))sb.From("user")sb.Where(sb.In("status", 1, 2, 5))sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)// Output:// SELECT id, name, COUNT(*) AS c FROM user WHERE status IN (?, ?, ?)// [1 2 5]Pre-defined SQL builders
This package includes the following pre-defined builders. API documentation and usage examples are available in thegodoc online documentation.
- Struct: Factory for creating builders based on struct definitions.
- CreateTableBuilder: Builder for
CREATE TABLE. - SelectBuilder: Builder for
SELECT. - InsertBuilder: Builder for
INSERT. - UpdateBuilder: Builder for
UPDATE. - DeleteBuilder: Builder for
DELETE. - UnionBuilder: Builder for
UNIONandUNION ALL. - CTEBuilder: Builder for Common Table Expression (CTE), e.g.
WITH name (col1, col2) AS (SELECT ...). - Buildf: Freestyle builder employing
fmt.Sprintf-like syntax. - Build: Advanced freestyle builder utilizing special syntax as defined inArgs#Compile.
- BuildNamed: Advanced freestyle builder that uses
${key}to reference values by key in a map.
A unique method,SQL(sql string), is implemented across all statement builders, enabling the insertion of any arbitrary SQL segment into a builder during SQL construction. This feature is particularly beneficial for crafting SQL statements that incorporate non-standard syntax required by OLTP or OLAP systems.
// Build a SQL to create a HIVE table.sql := sqlbuilder.CreateTable("users"). SQL("PARTITION BY (year)"). SQL("AS"). SQL( sqlbuilder.Select("columns[0] id", "columns[1] name", "columns[2] year"). From("`all-users.csv`"). String(), ). String()fmt.Println(sql)// Output:// CREATE TABLE users PARTITION BY (year) AS SELECT columns[0] id, columns[1] name, columns[2] year FROM `all-users.csv`Below are several utility methods designed to address special cases.
- Flatten enables the recursive conversion of an array-like variable into a flat slice of
[]interface{}. For example, invokingFlatten([]interface{"foo", []int{2, 3}})yields[]interface{}{"foo", 2, 3}. This method is compatible with builder methods such asIn,NotIn,Values, etc., facilitating the conversion of a typed array into[]interface{}or the merging of inputs. - List operates similarly to
Flatten, with the exception that its return value is specifically intended for use as builder arguments. For example,Buildf("my_func(%v)", List([]int{1, 2, 3})).Build()generates SQLmy_func(?, ?, ?)with arguments[]interface{}{1, 2, 3}. - Raw designates a string as a "raw string" within arguments. For instance,
Buildf("SELECT %v", Raw("NOW()")).Build()results in SQLSELECT NOW().
For detailed instructions on utilizing these builders, consult theexamples provided on GoDoc.
BuildWHERE clause
WHERE clause is the most important part of a SQL. We can useWhere method to add one or more conditions to a builder.
To simplify the construction ofWHERE clauses, a utility type namedCond is provided for condition building. All builders that supportWHERE clauses possess an anonymousCond field, enabling the invocation ofCond methods on these builders.
sb := sqlbuilder.Select("id").From("user")sb.Where( sb.In("status", 1, 2, 5), sb.Or( sb.Equal("name", "foo"), sb.Like("email", "foo@%"), ),)sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)// Output:// SELECT id FROM user WHERE status IN (?, ?, ?) AND (name = ? OR email LIKE ?)// [1 2 5 foo foo@%]There are many methods for building conditions.
- Cond.Equal/Cond.E/Cond.EQ:
field = value. - Cond.NotEqual/Cond.NE/Cond.NEQ:
field <> value. - Cond.GreaterThan/Cond.G/Cond.GT:
field > value. - Cond.GreaterEqualThan/Cond.GE/Cond.GTE:
field >= value. - Cond.LessThan/Cond.L/Cond.LT:
field < value. - Cond.LessEqualThan/Cond.LE/Cond.LTE:
field <= value. - Cond.In:
field IN (value1, value2, ...). - Cond.NotIn:
field NOT IN (value1, value2, ...). - Cond.Like:
field LIKE value. - Cond.ILike:
field ILIKE value. - Cond.NotLike:
field NOT LIKE value. - Cond.NotILike:
field NOT ILIKE value. - Cond.Between:
field BETWEEN lower AND upper. - Cond.NotBetween:
field NOT BETWEEN lower AND upper. - Cond.IsNull:
field IS NULL. - Cond.IsNotNull:
field IS NOT NULL. - Cond.Exists:
EXISTS (subquery). - Cond.NotExists:
NOT EXISTS (subquery). - Cond.Not:
NOT expr. - Cond.Any:
field op ANY (value1, value2, ...). - Cond.All:
field op ALL (value1, value2, ...). - Cond.Some:
field op SOME (value1, value2, ...). - Cond.IsDistinctFrom
field IS DISTINCT FROM value. - Cond.IsNotDistinctFrom
field IS NOT DISTINCT FROM value. - Cond.Var: A placeholder for any value.
There are also some methods to combine conditions.
ShareWHERE clause among builders
Due to the importance of theWHERE statement in SQL, we often need to continuously append conditions and even share some commonWHERE conditions among different builders. Therefore, we abstract theWHERE statement into aWhereClause struct, which can be used to create reusableWHERE conditions.
The following example illustrates how to transfer aWHERE clause from aSelectBuilder to anUpdateBuilder.
// Build a SQL to select a user from database.sb := Select("name", "level").From("users")sb.Where( sb.Equal("id", 1234),)fmt.Println(sb)ub := Update("users")ub.Set( ub.Add("level", 10),)// Set the WHERE clause of UPDATE to the WHERE clause of SELECT.ub.WhereClause = sb.WhereClausefmt.Println(ub)// Output:// SELECT name, level FROM users WHERE id = ?// UPDATE users SET level = level + ? WHERE id = ?Refer to theWhereClause examples to learn its usage.
BuildORDER BY clause
TheORDER BY clause is commonly used to sort query results. This package provides convenient methods to buildORDER BY clauses with proper ordering directions.
For scenarios where you need to order by multiple columns with different directions (ASC/DESC), useOrderByAsc andOrderByDesc methods. These methods can be chained to add multiple columns with their specific ordering.
sb := sqlbuilder.NewSelectBuilder()sb.Select("id", "name", "score").From("users")sb.OrderByDesc("score").OrderByAsc("name")sql, args := sb.Build()fmt.Println(sql)// Output:// SELECT id, name, score FROM users ORDER BY score DESC, name ASCThe olderOrderBy method combined withAsc/Desc is still available but deprecated, as it only supports a single ordering direction for all columns. The newOrderByAsc andOrderByDesc methods provide more flexibility and clarity when working with multiple columns.
Build SQL for different systems
SQL syntax and parameter placeholders can differ across systems. To address these variations, this package introduces a concept termed "flavor".
Currently, flavors such asMySQL,PostgreSQL,SQLite,SQLServer,CQL,ClickHouse,Presto,Oracle andInformix are supported. Should there be a demand for additional flavors, please submit an issue or a pull request.
By default, all builders utilizeDefaultFlavor for SQL construction, withMySQL as the default setting.
For greater readibility,PostgreSQL.NewSelectBuilder() can be used to instantiate aSelectBuilder with thePostgreSQL flavor. All builders can be created in this way.
UsingStruct as a light weight ORM
Struct encapsulates type information and struct fields, serving as a builder factory. UtilizingStruct methods, one can generateSELECT/INSERT/UPDATE/DELETE builders that are pre-configured for use with the struct, thereby conserving time and mitigating the risk of typographical errors in column name entries.
One can define a struct type and employ field tags to guideStruct in generating the appropriate builders.
type ATable struct { Field1 string // If a field doesn't has a tag, use "Field1" as column name in SQL. Field2 int `db:"field2"` // Use "db" in field tag to set column name used in SQL. Field3 int64 `db:"field3" fieldtag:"foo,bar"` // Set fieldtag to a field. We can call `WithTag` to include fields with tag or `WithoutTag` to exclude fields with tag. Field4 int64 `db:"field4" fieldtag:"foo"` // If we use `s.WithTag("foo").Select("t")`, columnes of SELECT are "t.field3" and "t.field4". Field5 string `db:"field5" fieldas:"f5_alias"` // Use "fieldas" in field tag to set a column alias (AS) used in SELECT. Ignored int32 `db:"-"` // If we set field name as "-", Struct will ignore it. unexported int // Unexported field is not visible to Struct. Quoted string `db:"quoted" fieldopt:"withquote"` // Add quote to the field using back quote or double quote. See `Flavor#Quote`. Empty uint `db:"empty" fieldopt:"omitempty"` // Omit the field in UPDATE if it is a nil or zero value. // The `omitempty` can be written as a function. // In this case, omit empty field `Tagged` when UPDATE for tag `tag1` and `tag3` but not `tag2`. Tagged string `db:"tagged" fieldopt:"omitempty(tag1,tag3)" fieldtag:"tag1,tag2,tag3"` // By default, the `SelectFrom("t")` will add the "t." to all names of fields matched tag. // We can add dot to field name to disable this behavior. FieldWithTableAlias string `db:"m.field"`}For detailed instructions on utilizingStruct, refer to theexamples.
Furthermore,Struct can be employed as a zero-configuration ORM. Unlike most ORM implementations that necessitate preliminary configurations for database connectivity,Struct operates without any configuration, functioning seamlessly with any SQL driver compatible withdatabase/sql.Struct does not invoke anydatabase/sql APIs; it solely generates the appropriate SQL statements with arguments forDB#Query/DB#Exec or an array of struct field addresses forRows#Scan/Row#Scan.
The following example demonstrates the use ofStruct as an ORM. It should be relatively straightforward for developers well-versed indatabase/sql APIs.
type User struct { ID int64 `db:"id" fieldtag:"pk"` Name string `db:"name"` Status int `db:"status"`}// A global variable for creating SQL builders.// All methods of userStruct are thread-safe.var userStruct = NewStruct(new(User))func ExampleStruct() { // Prepare SELECT query. // SELECT user.id, user.name, user.status FROM user WHERE id = 1234 sb := userStruct.SelectFrom("user") sb.Where(sb.Equal("id", 1234)) // Execute the query and scan the results into the user struct. sql, args := sb.Build() rows, _ := db.Query(sql, args...) defer rows.Close() // Scan row data and set value to user. // Assuming the following data is retrieved: // // | id | name | status | // |------|--------|--------| // | 1234 | huandu | 1 | var user User rows.Scan(userStruct.Addr(&user)...) fmt.Println(sql) fmt.Println(args) fmt.Printf("%#v", user) // Output: // SELECT user.id, user.name, user.status FROM user WHERE id = ? // [1234] // sqlbuilder.User{ID:1234, Name:"huandu", Status:1}}In numerous production environments, table column names adhere to the snake_case convention, e.g.,user_id. Conversely, struct fields in Go are typically in CamelCase to maintain public accessibility and satisfygolint. Employing thedb tag for each struct field can be redundant. To streamline this, a field mapper function can be utilized to establish a consistent rule for mapping struct field names to database column names.
TheDefaultFieldMapper serves as a global field mapper function, tasked with the conversion of field names to a desired style. By default, it is set tonil, effectively performing no action. Recognizing that the majority of table column names follow the snake_case convention, one can assignDefaultFieldMapper tosqlbuilder.SnakeCaseMapper. For instances that deviate from this norm, a custom mapper can be assigned to aStruct via theWithFieldMapper method.
Here are important considerations regarding the field mapper:
- Field tag has precedence over field mapper function - thus, mapper is ignored if the
dbtag is set; - Field mapper is called only once on a Struct when the Struct is used to create builder for the first time.
Refer to thefield mapper function sample for an illustrative example.
Nested SQL
Creating nested SQL is straightforward: simply use a builder as an argument for nesting.
Here is an illustrative example.
sb := sqlbuilder.NewSelectBuilder()fromSb := sqlbuilder.NewSelectBuilder()statusSb := sqlbuilder.NewSelectBuilder()sb.Select("id")sb.From(sb.BuilderAs(fromSb, "user")))sb.Where(sb.In("status", statusSb))fromSb.Select("id").From("user").Where(fromSb.GreaterThan("level", 4))statusSb.Select("status").From("config").Where(statusSb.Equal("state", 1))sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)// Output:// SELECT id FROM (SELECT id FROM user WHERE level > ?) AS user WHERE status IN (SELECT status FROM config WHERE state = ?)// [4 1]NestedJOIN
In addition to nested subqueries, you can also useBuilderAs to create nested JOINs. This is particularly useful when you need to join with a filtered or transformed dataset.
Here is an example showing how to join a table with a nested subquery:
sb := sqlbuilder.NewSelectBuilder()nestedSb := sqlbuilder.NewSelectBuilder()// Build the nested subquerynestedSb.Select("b.id", "b.user_id")nestedSb.From("users2 AS b")nestedSb.Where(nestedSb.GreaterThan("b.age", 20))// Build the main query with nested joinsb.Select("a.id", "a.user_id")sb.From("users AS a")sb.Join( sb.BuilderAs(nestedSb, "b"), "a.user_id = b.user_id",)sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)// Output:// SELECT a.id, a.user_id FROM users AS a JOIN (SELECT b.id, b.user_id FROM users2 AS b WHERE b.age > ?) AS b ON a.user_id = b.user_id// [20]Usesql.Named in a builder
Thesql.Named function, as defined in thedatabase/sql package, facilitates the creation of named arguments within SQL statements. This feature is essential for scenarios where an argument needs to be reused multiple times within a single SQL statement. Incorporating named arguments into a builder is straightforward: treat them as regular arguments.
Here is a sample.
now := time.Now().Unix()start := sql.Named("start", now-86400)end := sql.Named("end", now+86400)sb := sqlbuilder.NewSelectBuilder()sb.Select("name")sb.From("user")sb.Where( sb.Between("created_at", start, end), sb.GE("modified_at", start),)sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)// Output:// SELECT name FROM user WHERE created_at BETWEEN @start AND @end AND modified_at >= @start// [{{} start 1514458225} {{} end 1514544625}]Argument modifiers
Several argument modifiers are available:
List(arg)encapsulates a series of arguments. Givenargas a slice or array, for instance, a slice containing three integers, it compiles to?, ?, ?and is presented in the final arguments as three individual integers. This serves as a convenience tool, utilizable withinINexpressions or within theVALUESclause of anINSERT INTOstatement.TupleNames(names)andTuple(values)facilitate the representation of tuple syntax in SQL. For usage examples, refer toTuple.Named(name, arg)designates a named argument. Functionality is limited toBuildorBuildNamed, where it defines a named placeholder using the syntax${name}.Raw(expr)designatesexpras a plain string within SQL, as opposed to an argument. During the construction of a builder, raw expressions are directly embedded into the SQL string, omitting the need for?placeholders.
Freestyle builder
A builder essentially serves as a means to log arguments. For constructing lengthy SQL statements that incorporate numerous special syntax elements (e.g., special comments intended for a database proxy),Buildf can be employed to format the SQL string using a syntax akin tofmt.Sprintf.
sb := sqlbuilder.NewSelectBuilder()sb.Select("id").From("user")explain := sqlbuilder.Buildf("EXPLAIN %v LEFT JOIN SELECT * FROM banned WHERE state IN (%v, %v)", sb, 1, 2)sql, args := explain.Build()fmt.Println(sql)fmt.Println(args)// Output:// EXPLAIN SELECT id FROM user LEFT JOIN SELECT * FROM banned WHERE state IN (?, ?)// [1 2]Clone builders
TheClone methods make any builder reusable as a template. You can create a partially initialized builder once (even as a global), then callClone() to get an independent copy to customize per request. This avoids repeated setup while keeping shared templates immutable and safe for concurrent use.
Supported builders withClone:
- CreateTableBuilder
- CTEBuilder
- CTEQueryBuilder
- DeleteBuilder
- InsertBuilder
- SelectBuilder
- UnionBuilder
- UpdateBuilder
Example: define a global SELECT template and clone it per call
package yourpkgimport "github.com/huandu/go-sqlbuilder"// Global template — safe to reuse by cloning.var baseUserSelect = sqlbuilder.NewSelectBuilder(). Select("id", "name", "email"). From("users"). Where("deleted_at IS NULL")func ListActiveUsers(limit, offset int) (string, []interface{}) { sb := baseUserSelect.Clone() // independent copy sb.OrderByAsc("id") sb.Limit(limit).Offset(offset) return sb.Build()}func GetActiveUserByID(id int64) (string, []interface{}) { sb := baseUserSelect.Clone() // start from the same template sb.Where(sb.Equal("id", id)) sb.Limit(1) return sb.Build()}The same template pattern applies to other builders. For example, keep a baseUpdateBuilder with the table and commonSET clauses, or a baseCTEBuilder defining reusable CTEs, thenClone() and add query-specificWHERE/ORDER BY/LIMIT/RETURNING as needed.
Using special syntax to build SQL
Thesqlbuilder package incorporates special syntax for representing uncompiled SQL internally. To leverage this syntax for developing customized tools, theBuild function can be utilized to compile it with the necessary arguments.
The format string employs special syntax for representing arguments:
$?references successive arguments supplied in the function call, functioning similarly to%vinfmt.Sprintf.$0,$1, ...,$nreference the nth argument provided in the call; subsequent$?will then refer to arguments n+1 onwards.${name}references a named argument defined byNamedusing the specifiedname.$$represents a literal"$"character.
sb := sqlbuilder.NewSelectBuilder()sb.Select("id").From("user").Where(sb.In("status", 1, 2))b := sqlbuilder.Build("EXPLAIN $? LEFT JOIN SELECT * FROM $? WHERE created_at > $? AND state IN (${states}) AND modified_at BETWEEN $2 AND $?", sb, sqlbuilder.Raw("banned"), 1514458225, 1514544625, sqlbuilder.Named("states", sqlbuilder.List([]int{3, 4, 5})))sql, args := b.Build()fmt.Println(sql)fmt.Println(args)// Output:// EXPLAIN SELECT id FROM user WHERE status IN (?, ?) LEFT JOIN SELECT * FROM banned WHERE created_at > ? AND state IN (?, ?, ?) AND modified_at BETWEEN ? AND ?// [1 2 1514458225 3 4 5 1514458225 1514544625]For scenarios where only the${name} syntax is required to reference named arguments, utilizeBuildNamed. This function disables all special syntax except for${name} and$$.
Interpolateargs in thesql
Certain SQL-like drivers, such as those for Redis or Elasticsearch, do not implement theStmtExecContext#ExecContext method. These drivers encounter issues whenlen(args) > 0. The sole workaround is to interpolateargs directly into thesql string and then execute the resulting query with the driver.
The interpolation feature in this package is designed to provide a "basically sufficient" level of functionality, rather than a capability that rivals the comprehensive features of various SQL drivers and DBMS systems.
Security warning: While efforts are made to escape special characters in interpolation methods, this approach remains less secure than usingStmt as implemented by SQL drivers.
This feature draws inspiration from the interpolation capabilities found in thegithub.com/go-sql-driver/mysql package.
Here is an example specifically for MySQL:
sb := MySQL.NewSelectBuilder()sb.Select("name").From("user").Where( sb.NE("id", 1234), sb.E("name", "Charmy Liu"), sb.Like("desc", "%mother's day%"),)sql, args := sb.Build()query, err := MySQL.Interpolate(sql, args)fmt.Println(query)fmt.Println(err)// Output:// SELECT name FROM user WHERE id <> 1234 AND name = 'Charmy Liu' AND desc LIKE '%mother\'s day%'// <nil>Here is an example for PostgreSQL, noting that dollar quoting is supported:
// Only the last `$1` is interpolated.// Others are not interpolated as they are inside dollar quote (the `$$`).query, err := PostgreSQL.Interpolate(`CREATE FUNCTION dup(in int, out f1 int, out f2 text) AS $$ SELECT $1, CAST($1 AS text) || ' is text'$$LANGUAGE SQL;SELECT * FROM dup($1);`, []interface{}{42})fmt.Println(query)fmt.Println(err)// Output://// CREATE FUNCTION dup(in int, out f1 int, out f2 text) AS $$// SELECT $1, CAST($1 AS text) || ' is text'// $$// LANGUAGE SQL;//// SELECT * FROM dup(42);// <nil>License
This package is licensed under the MIT license. For more information, refer to the LICENSE file.
Documentation¶
Overview¶
Package sqlbuilder is a flexible and powerful tool to build SQL string and associated args.
Index¶
- Variables
- func Escape(ident string) string
- func EscapeAll(ident ...string) []string
- func Flatten(slices interface{}) (flattened []interface{})
- func List(arg interface{}) interface{}
- func Named(name string, arg interface{}) interface{}
- func Raw(expr string) interface{}
- func SnakeCaseMapper(field string) string
- func Tuple(values ...interface{}) interface{}
- func TupleNames(names ...string) string
- type Args
- func (args *Args) Add(arg interface{}) string
- func (args *Args) Compile(format string, initialValue ...interface{}) (query string, values []interface{})
- func (args *Args) CompileWithFlavor(format string, flavor Flavor, initialValue ...interface{}) (query string, values []interface{})
- func (args *Args) Replace(placeholder string, arg interface{})
- func (args *Args) Value(arg string) interface{}
- type Builder
- type CTEBuilder
- func (cteb *CTEBuilder) Build() (sql string, args []interface{})
- func (cteb *CTEBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{})
- func (cteb *CTEBuilder) Clone() *CTEBuilder
- func (cteb *CTEBuilder) DeleteFrom(table string) *DeleteBuilder
- func (cteb *CTEBuilder) Flavor() Flavor
- func (cteb *CTEBuilder) SQL(sql string) *CTEBuilder
- func (cteb *CTEBuilder) Select(col ...string) *SelectBuilder
- func (cteb *CTEBuilder) SetFlavor(flavor Flavor) (old Flavor)
- func (cteb *CTEBuilder) String() string
- func (cteb *CTEBuilder) TableNames() []string
- func (cteb *CTEBuilder) Update(table string) *UpdateBuilder
- func (cteb *CTEBuilder) With(queries ...*CTEQueryBuilder) *CTEBuilder
- func (cteb *CTEBuilder) WithRecursive(queries ...*CTEQueryBuilder) *CTEBuilder
- type CTEQueryBuilder
- func (ctetb *CTEQueryBuilder) AddToTableList() *CTEQueryBuilder
- func (ctetb *CTEQueryBuilder) As(builder Builder) *CTEQueryBuilder
- func (ctetb *CTEQueryBuilder) Build() (sql string, args []interface{})
- func (ctetb *CTEQueryBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{})
- func (ctetb *CTEQueryBuilder) Clone() *CTEQueryBuilder
- func (ctetb *CTEQueryBuilder) Flavor() Flavor
- func (ctetb *CTEQueryBuilder) SQL(sql string) *CTEQueryBuilder
- func (ctetb *CTEQueryBuilder) SetFlavor(flavor Flavor) (old Flavor)
- func (ctetb *CTEQueryBuilder) ShouldAddToTableList() bool
- func (ctetb *CTEQueryBuilder) String() string
- func (ctetb *CTEQueryBuilder) Table(name string, cols ...string) *CTEQueryBuilder
- func (ctetb *CTEQueryBuilder) TableName() string
- type CTETableBuilderdeprecated
- type Cond
- func (c *Cond) All(field, op string, values ...interface{}) string
- func (c *Cond) And(andExpr ...string) string
- func (c *Cond) Any(field, op string, values ...interface{}) string
- func (c *Cond) Between(field string, lower, upper interface{}) string
- func (c *Cond) E(field string, value interface{}) string
- func (c *Cond) EQ(field string, value interface{}) string
- func (c *Cond) Equal(field string, value interface{}) string
- func (c *Cond) Exists(subquery interface{}) string
- func (c *Cond) G(field string, value interface{}) string
- func (c *Cond) GE(field string, value interface{}) string
- func (c *Cond) GT(field string, value interface{}) string
- func (c *Cond) GTE(field string, value interface{}) string
- func (c *Cond) GreaterEqualThan(field string, value interface{}) string
- func (c *Cond) GreaterThan(field string, value interface{}) string
- func (c *Cond) ILike(field string, value interface{}) string
- func (c *Cond) In(field string, values ...interface{}) string
- func (c *Cond) IsDistinctFrom(field string, value interface{}) string
- func (c *Cond) IsNotDistinctFrom(field string, value interface{}) string
- func (c *Cond) IsNotNull(field string) string
- func (c *Cond) IsNull(field string) string
- func (c *Cond) L(field string, value interface{}) string
- func (c *Cond) LE(field string, value interface{}) string
- func (c *Cond) LT(field string, value interface{}) string
- func (c *Cond) LTE(field string, value interface{}) string
- func (c *Cond) LessEqualThan(field string, value interface{}) string
- func (c *Cond) LessThan(field string, value interface{}) string
- func (c *Cond) Like(field string, value interface{}) string
- func (c *Cond) NE(field string, value interface{}) string
- func (c *Cond) NEQ(field string, value interface{}) string
- func (c *Cond) Not(notExpr string) string
- func (c *Cond) NotBetween(field string, lower, upper interface{}) string
- func (c *Cond) NotEqual(field string, value interface{}) string
- func (c *Cond) NotExists(subquery interface{}) string
- func (c *Cond) NotILike(field string, value interface{}) string
- func (c *Cond) NotIn(field string, values ...interface{}) string
- func (c *Cond) NotLike(field string, value interface{}) string
- func (c *Cond) Or(orExpr ...string) string
- func (c *Cond) Some(field, op string, values ...interface{}) string
- func (c *Cond) Var(value interface{}) string
- type CreateTableBuilder
- func (ctb *CreateTableBuilder) Build() (sql string, args []interface{})
- func (ctb *CreateTableBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{})
- func (ctb *CreateTableBuilder) Clone() *CreateTableBuilder
- func (ctb *CreateTableBuilder) CreateTable(table string) *CreateTableBuilder
- func (ctb *CreateTableBuilder) CreateTempTable(table string) *CreateTableBuilder
- func (ctb *CreateTableBuilder) Define(def ...string) *CreateTableBuilder
- func (ctb *CreateTableBuilder) Flavor() Flavor
- func (ctb *CreateTableBuilder) IfNotExists() *CreateTableBuilder
- func (ctb *CreateTableBuilder) NumDefine() int
- func (ctb *CreateTableBuilder) Option(opt ...string) *CreateTableBuilder
- func (ctb *CreateTableBuilder) SQL(sql string) *CreateTableBuilder
- func (ctb *CreateTableBuilder) SetFlavor(flavor Flavor) (old Flavor)
- func (ctb *CreateTableBuilder) String() string
- func (ctb *CreateTableBuilder) Var(arg interface{}) string
- type DeleteBuilder
- func (db *DeleteBuilder) AddWhereClause(whereClause *WhereClause) *DeleteBuilder
- func (db *DeleteBuilder) Asc() *DeleteBuilderdeprecated
- func (db *DeleteBuilder) Build() (sql string, args []interface{})
- func (db *DeleteBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{})
- func (db *DeleteBuilder) Clone() *DeleteBuilder
- func (db *DeleteBuilder) DeleteFrom(table ...string) *DeleteBuilder
- func (db *DeleteBuilder) Desc() *DeleteBuilderdeprecated
- func (db *DeleteBuilder) Flavor() Flavor
- func (db *DeleteBuilder) Limit(limit int) *DeleteBuilder
- func (db *DeleteBuilder) OrderBy(col ...string) *DeleteBuilderdeprecated
- func (db *DeleteBuilder) OrderByAsc(col string) *DeleteBuilder
- func (db *DeleteBuilder) OrderByDesc(col string) *DeleteBuilder
- func (db *DeleteBuilder) Returning(col ...string) *DeleteBuilder
- func (db *DeleteBuilder) SQL(sql string) *DeleteBuilder
- func (db *DeleteBuilder) SetFlavor(flavor Flavor) (old Flavor)
- func (db *DeleteBuilder) String() string
- func (db *DeleteBuilder) TableNames() []string
- func (db *DeleteBuilder) Where(andExpr ...string) *DeleteBuilder
- func (db *DeleteBuilder) With(builder *CTEBuilder) *DeleteBuilder
- type FieldMapperFunc
- type Flavor
- func (f Flavor) Interpolate(sql string, args []interface{}) (string, error)
- func (f Flavor) NewCTEBuilder() *CTEBuilder
- func (f Flavor) NewCTEQueryBuilder() *CTEQueryBuilder
- func (f Flavor) NewCreateTableBuilder() *CreateTableBuilder
- func (f Flavor) NewDeleteBuilder() *DeleteBuilder
- func (f Flavor) NewInsertBuilder() *InsertBuilder
- func (f Flavor) NewSelectBuilder() *SelectBuilder
- func (f Flavor) NewUnionBuilder() *UnionBuilder
- func (f Flavor) NewUpdateBuilder() *UpdateBuilder
- func (f Flavor) PrepareInsertIgnore(table string, ib *InsertBuilder)
- func (f Flavor) Quote(name string) string
- func (f Flavor) String() string
- type GetAliasFunc
- type InsertBuilder
- func (ib *InsertBuilder) Build() (sql string, args []interface{})
- func (ib *InsertBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{})
- func (ib *InsertBuilder) Clone() *InsertBuilder
- func (ib *InsertBuilder) Cols(col ...string) *InsertBuilder
- func (ib *InsertBuilder) Flavor() Flavor
- func (ib *InsertBuilder) InsertIgnoreInto(table string) *InsertBuilder
- func (ib *InsertBuilder) InsertInto(table string) *InsertBuilder
- func (ib *InsertBuilder) NumValue() int
- func (ib *InsertBuilder) ReplaceInto(table string) *InsertBuilder
- func (ib *InsertBuilder) Returning(col ...string) *InsertBuilder
- func (ib *InsertBuilder) SQL(sql string) *InsertBuilder
- func (isb *InsertBuilder) Select(col ...string) *SelectBuilder
- func (ib *InsertBuilder) SetFlavor(flavor Flavor) (old Flavor)
- func (ib *InsertBuilder) String() string
- func (ib *InsertBuilder) Values(value ...interface{}) *InsertBuilder
- func (ib *InsertBuilder) Var(arg interface{}) string
- type JoinOption
- type SelectBuilder
- func (sb *SelectBuilder) AddWhereClause(whereClause *WhereClause) *SelectBuilder
- func (sb *SelectBuilder) As(name, alias string) string
- func (sb *SelectBuilder) Asc() *SelectBuilderdeprecated
- func (sb *SelectBuilder) Build() (sql string, args []interface{})
- func (sb *SelectBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{})
- func (sb *SelectBuilder) BuilderAs(builder Builder, alias string) string
- func (sb *SelectBuilder) Clone() *SelectBuilder
- func (sb *SelectBuilder) Desc() *SelectBuilderdeprecated
- func (sb *SelectBuilder) Distinct() *SelectBuilder
- func (sb *SelectBuilder) Flavor() Flavor
- func (sb *SelectBuilder) ForShare() *SelectBuilder
- func (sb *SelectBuilder) ForUpdate() *SelectBuilder
- func (sb *SelectBuilder) From(table ...string) *SelectBuilder
- func (sb *SelectBuilder) GroupBy(col ...string) *SelectBuilder
- func (sb *SelectBuilder) Having(andExpr ...string) *SelectBuilder
- func (sb *SelectBuilder) Join(table string, onExpr ...string) *SelectBuilder
- func (sb *SelectBuilder) JoinWithOption(option JoinOption, table string, onExpr ...string) *SelectBuilder
- func (sb *SelectBuilder) LateralAs(builder Builder, alias string) string
- func (sb *SelectBuilder) Limit(limit int) *SelectBuilder
- func (sb *SelectBuilder) NumCol() int
- func (sb *SelectBuilder) Offset(offset int) *SelectBuilder
- func (sb *SelectBuilder) OrderBy(col ...string) *SelectBuilderdeprecated
- func (sb *SelectBuilder) OrderByAsc(col string) *SelectBuilder
- func (sb *SelectBuilder) OrderByDesc(col string) *SelectBuilder
- func (sb *SelectBuilder) SQL(sql string) *SelectBuilder
- func (sb *SelectBuilder) Select(col ...string) *SelectBuilder
- func (sb *SelectBuilder) SelectMore(col ...string) *SelectBuilder
- func (sb *SelectBuilder) SetFlavor(flavor Flavor) (old Flavor)
- func (sb *SelectBuilder) String() string
- func (sb *SelectBuilder) TableNames() []string
- func (sb *SelectBuilder) Where(andExpr ...string) *SelectBuilder
- func (sb *SelectBuilder) With(builder *CTEBuilder) *SelectBuilder
- type Struct
- func (s *Struct) Addr(st interface{}) []interface{}
- func (s *Struct) AddrForTag(tag string, st interface{}) []interface{}deprecated
- func (s *Struct) AddrWithCols(cols []string, st interface{}) []interface{}
- func (s *Struct) Columns() []string
- func (s *Struct) ColumnsForTag(tag string) (cols []string)deprecated
- func (s *Struct) DeleteFrom(table string) *DeleteBuilder
- func (s *Struct) For(flavor Flavor) *Struct
- func (s *Struct) ForeachRead(trans func(dbtag string, isQuoted bool, field reflect.StructField))
- func (s *Struct) ForeachWrite(trans func(dbtag string, isQuoted bool, field reflect.StructField))
- func (s *Struct) InsertIgnoreInto(table string, value ...interface{}) *InsertBuilder
- func (s *Struct) InsertIgnoreIntoForTag(table string, tag string, value ...interface{}) *InsertBuilderdeprecated
- func (s *Struct) InsertInto(table string, value ...interface{}) *InsertBuilder
- func (s *Struct) InsertIntoForTag(table string, tag string, value ...interface{}) *InsertBuilderdeprecated
- func (s *Struct) ReplaceInto(table string, value ...interface{}) *InsertBuilder
- func (s *Struct) ReplaceIntoForTag(table string, tag string, value ...interface{}) *InsertBuilderdeprecated
- func (s *Struct) SelectFrom(table string) *SelectBuilder
- func (s *Struct) SelectFromForTag(table string, tag string) (sb *SelectBuilder)deprecated
- func (s *Struct) Update(table string, value interface{}) *UpdateBuilder
- func (s *Struct) UpdateForTag(table string, tag string, value interface{}) *UpdateBuilderdeprecated
- func (s *Struct) Values(st interface{}) []interface{}
- func (s *Struct) ValuesForTag(tag string, value interface{}) (values []interface{})deprecated
- func (s *Struct) WithFieldMapper(mapper FieldMapperFunc) *Struct
- func (s *Struct) WithTag(tags ...string) *Struct
- func (s *Struct) WithoutTag(tags ...string) *Struct
- type UnionBuilder
- func (ub *UnionBuilder) Asc() *UnionBuilderdeprecated
- func (ub *UnionBuilder) Build() (sql string, args []interface{})
- func (ub *UnionBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{})
- func (ub *UnionBuilder) Clone() *UnionBuilder
- func (ub *UnionBuilder) Desc() *UnionBuilderdeprecated
- func (ub *UnionBuilder) Flavor() Flavor
- func (ub *UnionBuilder) Limit(limit int) *UnionBuilder
- func (ub *UnionBuilder) Offset(offset int) *UnionBuilder
- func (ub *UnionBuilder) OrderBy(col ...string) *UnionBuilderdeprecated
- func (ub *UnionBuilder) OrderByAsc(col string) *UnionBuilder
- func (ub *UnionBuilder) OrderByDesc(col string) *UnionBuilder
- func (ub *UnionBuilder) SQL(sql string) *UnionBuilder
- func (ub *UnionBuilder) SetFlavor(flavor Flavor) (old Flavor)
- func (ub *UnionBuilder) String() string
- func (ub *UnionBuilder) Union(builders ...Builder) *UnionBuilder
- func (ub *UnionBuilder) UnionAll(builders ...Builder) *UnionBuilder
- func (ub *UnionBuilder) Var(arg interface{}) string
- type UpdateBuilder
- func (ub *UpdateBuilder) Add(field string, value interface{}) string
- func (ub *UpdateBuilder) AddWhereClause(whereClause *WhereClause) *UpdateBuilder
- func (ub *UpdateBuilder) Asc() *UpdateBuilderdeprecated
- func (ub *UpdateBuilder) Assign(field string, value interface{}) string
- func (ub *UpdateBuilder) Build() (sql string, args []interface{})
- func (ub *UpdateBuilder) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{})
- func (ub *UpdateBuilder) Clone() *UpdateBuilder
- func (ub *UpdateBuilder) Decr(field string) string
- func (ub *UpdateBuilder) Desc() *UpdateBuilderdeprecated
- func (ub *UpdateBuilder) Div(field string, value interface{}) string
- func (ub *UpdateBuilder) Flavor() Flavor
- func (ub *UpdateBuilder) Incr(field string) string
- func (ub *UpdateBuilder) Limit(limit int) *UpdateBuilder
- func (ub *UpdateBuilder) Mul(field string, value interface{}) string
- func (ub *UpdateBuilder) NumAssignment() int
- func (ub *UpdateBuilder) OrderBy(col ...string) *UpdateBuilderdeprecated
- func (ub *UpdateBuilder) OrderByAsc(col string) *UpdateBuilder
- func (ub *UpdateBuilder) OrderByDesc(col string) *UpdateBuilder
- func (ub *UpdateBuilder) Returning(col ...string) *UpdateBuilder
- func (ub *UpdateBuilder) SQL(sql string) *UpdateBuilder
- func (ub *UpdateBuilder) Set(assignment ...string) *UpdateBuilder
- func (ub *UpdateBuilder) SetFlavor(flavor Flavor) (old Flavor)
- func (ub *UpdateBuilder) SetMore(assignment ...string) *UpdateBuilder
- func (ub *UpdateBuilder) String() string
- func (ub *UpdateBuilder) Sub(field string, value interface{}) string
- func (ub *UpdateBuilder) TableNames() (tableNames []string)
- func (ub *UpdateBuilder) Update(table ...string) *UpdateBuilder
- func (ub *UpdateBuilder) Where(andExpr ...string) *UpdateBuilder
- func (ub *UpdateBuilder) With(builder *CTEBuilder) *UpdateBuilder
- type WhereClause
- func (wc *WhereClause) AddWhereClause(whereClause *WhereClause) *WhereClause
- func (wc *WhereClause) AddWhereExpr(args *Args, andExpr ...string) *WhereClause
- func (wc *WhereClause) Build() (sql string, args []interface{})
- func (wc *WhereClause) BuildWithFlavor(flavor Flavor, initialArg ...interface{}) (sql string, args []interface{})
- func (wc *WhereClause) Flavor() Flavor
- func (wc *WhereClause) SetFlavor(flavor Flavor) (old Flavor)
Examples¶
- Build
- BuildNamed
- Buildf
- CTEBuilder
- CTEBuilder (Delete)
- CTEBuilder (Update)
- CreateTable
- CreateTableBuilder
- CreateTableBuilder (TempTable)
- CreateTableBuilder.NumDefine
- CreateTableBuilder.SQL
- DeleteBuilder
- DeleteBuilder.Returning
- DeleteBuilder.SQL
- DeleteBuilder.With
- DeleteFrom
- FieldMapperFunc
- Flavor
- Flavor.Interpolate (Cql)
- Flavor.Interpolate (Infomix)
- Flavor.Interpolate (MySQL)
- Flavor.Interpolate (Oracle)
- Flavor.Interpolate (PostgreSQL)
- Flavor.Interpolate (SqlServer)
- Flavor.Interpolate (Sqlite)
- InsertBuilder
- InsertBuilder (FlavorOracle)
- InsertBuilder (InsertIgnore)
- InsertBuilder (InsertIgnore_clickhouse)
- InsertBuilder (InsertIgnore_postgres)
- InsertBuilder (InsertIgnore_sqlite)
- InsertBuilder (ReplaceInto)
- InsertBuilder (SubSelect)
- InsertBuilder (SubSelect_informix)
- InsertBuilder (SubSelect_oracle)
- InsertBuilder.NumValue
- InsertBuilder.Returning
- InsertBuilder.SQL
- InsertIgnoreInto
- InsertInto
- ReplaceInto
- Select
- SelectBuilder
- SelectBuilder (AdvancedUsage)
- SelectBuilder (CustomSELECT)
- SelectBuilder (Join)
- SelectBuilder (Limit_offset)
- SelectBuilder (NestedJoin)
- SelectBuilder (VarInCols)
- SelectBuilder.ForUpdate
- SelectBuilder.LateralAs
- SelectBuilder.NumCol
- SelectBuilder.OrderByAsc
- SelectBuilder.OrderByAsc (Multiple)
- SelectBuilder.OrderByDesc
- SelectBuilder.SQL
- SelectBuilder.With
- Struct (BuildDELETE)
- Struct (BuildINSERT)
- Struct (BuildJOIN)
- Struct (BuildUPDATE)
- Struct (ForCQL)
- Struct (ForPostgreSQL)
- Struct (UseStructAsORM)
- Struct.WithTag
- Struct.WithoutTag
- Tuple
- Union
- UnionAll
- UnionBuilder (Limit_offset)
- UnionBuilder.SQL
- Update
- UpdateBuilder
- UpdateBuilder.NumAssignment
- UpdateBuilder.Returning
- UpdateBuilder.SQL
- UpdateBuilder.SetMore
- UpdateBuilder.With
- WhereClause
- WhereClause (ClearWhereClause)
- WhereClause (SharedAmongBuilders)
- WhereClause.AddWhereClause
- WhereClause.AddWhereExpr
- With
- WithFlavor
- WithRecursive
Constants¶
This section is empty.
Variables¶
var (// DefaultFieldMapper is the default field name to table column name mapper func.// It's nil by default which means field name will be kept as it is.//// If a Struct has its own mapper func, the DefaultFieldMapper is ignored in this Struct.// Field tag has precedence over all kinds of field mapper functions.//// Field mapper is called only once on a Struct when the Struct is used to create builder for the first time.DefaultFieldMapperFieldMapperFunc// DefaultGetAlias is the default alias and dbtag get funcDefaultGetAliasGetAliasFunc)
var (// ErrInterpolateNotImplemented means the method or feature is not implemented right now.ErrInterpolateNotImplemented =errors.New("go-sqlbuilder: interpolation for this flavor is not implemented")// ErrInterpolateMissingArgs means there are some args missing in query, so it's not possible to// prepare a query with such args.ErrInterpolateMissingArgs =errors.New("go-sqlbuilder: not enough args when interpolating")// ErrInterpolateUnsupportedArgs means that some types of the args are not supported.ErrInterpolateUnsupportedArgs =errors.New("go-sqlbuilder: unsupported args when interpolating"))
var (// DBTag is the struct tag to describe the name for a field in struct.DBTag = "db"// FieldTag is the struct tag to describe the tag name for a field in struct.// Use "," to separate different tags.FieldTag = "fieldtag"// FieldOpt is the options for a struct field.// As db column can contain "," in theory, field options should be provided in a separated tag.FieldOpt = "fieldopt"// FieldAs is the column alias (AS) for a struct field.FieldAs = "fieldas")
var (// DefaultFlavor is the default flavor for all builders.DefaultFlavor =MySQL)
Functions¶
funcFlatten¶
func Flatten(slices interface{}) (flattened []interface{})Flatten recursively extracts values in slices and returnsa flattened []interface{} with all values.If slices is not a slice, return `[]interface{}{slices}`.
funcList¶
func List(arg interface{}) interface{}List marks arg as a list of data.If arg is `[]int{1, 2, 3}`, it will be compiled to `?, ?, ?` with args `[1 2 3]`.
funcNamed¶
func Named(namestring, arg interface{}) interface{}
Named creates a named argument.Unlike `sql.Named`, this named argument works only with `Build` or `BuildNamed` for convenienceand will be replaced to a `?` after `Compile`.
funcRaw¶
func Raw(exprstring) interface{}
Raw marks the expr as a raw value which will not be added to args.
funcSnakeCaseMapper¶added inv1.12.0
SnakeCaseMapper is a field mapper which can convert field name from CamelCase to snake_case.
For instance, it will convert "MyField" to "my_field".
SnakeCaseMapper uses package "xstrings" to do the conversion.Seehttps://pkg.go.dev/github.com/huandu/xstrings#ToSnakeCase for conversion rules.
funcTuple¶added inv1.22.0
func Tuple(values ...interface{}) interface{}Tuple wraps values into a tuple and can be used as a single value.
Example¶
sb := Select("id", "name").From("user")sb.Where(sb.In(TupleNames("type", "status"),Tuple("web", 1),Tuple("app", 1),Tuple("app", 2),),)sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT id, name FROM user WHERE (type, status) IN ((?, ?), (?, ?), (?, ?))[web 1 app 1 app 2]
funcTupleNames¶added inv1.22.0
TupleNames joins names with tuple format.The names is not escaped. Use `EscapeAll` to escape them if necessary.
Types¶
typeArgs¶
type Args struct {// The default flavor used by `Args#Compile`FlavorFlavor// contains filtered or unexported fields}Args stores arguments associated with a SQL.
func (*Args)Compile¶
func (args *Args) Compile(formatstring, initialValue ...interface{}) (querystring, values []interface{})
Compile compiles builder's format to standard sql and returns associated args.
The format string uses a special syntax to represent arguments.
$? refers successive arguments passed in the call. It works similar as `%v` in `fmt.Sprintf`.$0 $1 ... $n refers nth-argument passed in the call. Next $? will use arguments n+1.${name} refers a named argument created by `Named` with `name`.$$ is a "$" string.func (*Args)CompileWithFlavor¶
func (args *Args) CompileWithFlavor(formatstring, flavorFlavor, initialValue ...interface{}) (querystring, values []interface{})
CompileWithFlavor compiles builder's format to standard sql with flavor and returns associated args.
See doc for `Compile` to learn details.
typeBuilder¶
type Builder interface {Build() (sqlstring, args []interface{})BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})Flavor()Flavor}Builder is a general SQL builder.It's used by Args to create nested SQL like the `IN` expression in`SELECT * FROM t1 WHERE id IN (SELECT id FROM t2)`.
funcBuild¶
Build creates a Builder from a format string.The format string uses special syntax to represent arguments.See doc in `Args#Compile` for syntax details.
Example¶
sb := NewSelectBuilder()sb.Select("id").From("user").Where(sb.In("status", 1, 2))b := Build("EXPLAIN $? LEFT JOIN SELECT * FROM $? WHERE created_at > $? AND state IN (${states}) AND modified_at BETWEEN $2 AND $?",sb, Raw("banned"), 1514458225, 1514544625, Named("states", List([]int{3, 4, 5})))s, args := b.Build()fmt.Println(s)fmt.Println(args)Output:EXPLAIN SELECT id FROM user WHERE status IN (?, ?) LEFT JOIN SELECT * FROM banned WHERE created_at > ? AND state IN (?, ?, ?) AND modified_at BETWEEN ? AND ?[1 2 1514458225 3 4 5 1514458225 1514544625]
funcBuildNamed¶
BuildNamed creates a Builder from a format string.The format string uses `${key}` to refer the value of named by key.
Example¶
b := BuildNamed("SELECT * FROM ${table} WHERE status IN (${status}) AND name LIKE ${name} AND created_at > ${time} AND modified_at < ${time} + 86400",map[string]interface{}{"time": sql.Named("start", 1234567890),"status": List([]int{1, 2, 5}),"name": "Huan%","table": Raw("user"),})s, args := b.Build()fmt.Println(s)fmt.Println(args)Output:SELECT * FROM user WHERE status IN (?, ?, ?) AND name LIKE ? AND created_at > @start AND modified_at < @start + 86400[1 2 5 Huan% {{} start 1234567890}]
funcBuildf¶
Buildf creates a Builder from a format string using `fmt.Sprintf`-like syntax.As all arguments will be converted to a string internally, e.g. "$0",only `%v` and `%s` are valid.
Example¶
sb := NewSelectBuilder()sb.Select("id").From("user")explain := Buildf("EXPLAIN %v LEFT JOIN SELECT * FROM banned WHERE state IN (%v, %v)", sb, 1, 2)s, args := explain.Build()fmt.Println(s)fmt.Println(args)Output:EXPLAIN SELECT id FROM user LEFT JOIN SELECT * FROM banned WHERE state IN (?, ?)[1 2]
funcWithFlavor¶
WithFlavor creates a new Builder based on builder with a default flavor.
Example¶
sql, args := WithFlavor(Buildf("SELECT * FROM foo WHERE id = %v", 1234), PostgreSQL).Build()fmt.Println(sql)fmt.Println(args)// Explicitly use MySQL as the flavor.sql, args = WithFlavor(Buildf("SELECT * FROM foo WHERE id = %v", 1234), PostgreSQL).BuildWithFlavor(MySQL)fmt.Println(sql)fmt.Println(args)// Explicitly use MySQL as the informix.sql, args = WithFlavor(Buildf("SELECT * FROM foo WHERE id = %v", 1234), Informix).Build()fmt.Println(sql)fmt.Println(args)Output:SELECT * FROM foo WHERE id = $1[1234]SELECT * FROM foo WHERE id = ?[1234]SELECT * FROM foo WHERE id = ?[1234]
typeCTEBuilder¶added inv1.28.0
type CTEBuilder struct {// contains filtered or unexported fields}CTEBuilder is a CTE (Common Table Expression) builder.
Example¶
usersBuilder := Select("id", "name", "level").From("users")usersBuilder.Where(usersBuilder.GreaterEqualThan("level", 10),)cteb := With(CTETable("valid_users").As(usersBuilder),)fmt.Println(cteb)sb := Select("valid_users.id", "valid_users.name", "orders.id").From("users").With(cteb).Join("orders", "users.id = orders.user_id")sb.Where(sb.LessEqualThan("orders.price", 200),"valid_users.level < orders.min_level",).OrderByDesc("orders.price")sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)fmt.Println(sb.TableNames())Output:WITH valid_users AS (SELECT id, name, level FROM users WHERE level >= ?)WITH valid_users AS (SELECT id, name, level FROM users WHERE level >= ?) SELECT valid_users.id, valid_users.name, orders.id FROM users, valid_users JOIN orders ON users.id = orders.user_id WHERE orders.price <= ? AND valid_users.level < orders.min_level ORDER BY orders.price DESC[10 200][users valid_users]
Example (Delete)¶
sql := With(CTETable("users", "user_id").As(Select("user_id").From("cheaters"),),).DeleteFrom("awards").Where("users.user_id = awards.user_id",).String()fmt.Println(sql)Output:WITH users (user_id) AS (SELECT user_id FROM cheaters) DELETE FROM awards, users WHERE users.user_id = awards.user_id
Example (Update)¶
builder := With(CTETable("users", "user_id").As(Select("user_id").From("vip_users"),),).Update("orders").Set("orders.transport_fee = 0",).Where("users.user_id = orders.user_id",)sqlForMySQL, _ := builder.BuildWithFlavor(MySQL)sqlForPostgreSQL, _ := builder.BuildWithFlavor(PostgreSQL)fmt.Println(sqlForMySQL)fmt.Println(sqlForPostgreSQL)Output:WITH users (user_id) AS (SELECT user_id FROM vip_users) UPDATE orders, users SET orders.transport_fee = 0 WHERE users.user_id = orders.user_idWITH users (user_id) AS (SELECT user_id FROM vip_users) UPDATE orders SET orders.transport_fee = 0 FROM users WHERE users.user_id = orders.user_id
funcWith¶added inv1.28.0
func With(tables ...*CTEQueryBuilder) *CTEBuilder
With creates a new CTE builder with default flavor.
Example¶
sb := With(CTETable("users", "id", "name").As(Select("id", "name").From("users").Where("name IS NOT NULL"),),CTETable("devices").As(Select("device_id").From("devices"),),).Select("users.id", "orders.id", "devices.device_id").Join("orders","users.id = orders.user_id","devices.device_id = orders.device_id",)fmt.Println(sb)Output:WITH users (id, name) AS (SELECT id, name FROM users WHERE name IS NOT NULL), devices AS (SELECT device_id FROM devices) SELECT users.id, orders.id, devices.device_id FROM users, devices JOIN orders ON users.id = orders.user_id AND devices.device_id = orders.device_id
funcWithRecursive¶added inv1.29.0
func WithRecursive(tables ...*CTEQueryBuilder) *CTEBuilder
WithRecursive creates a new recursive CTE builder with default flavor.
Example¶
sb := WithRecursive(CTEQuery("source_accounts", "id", "parent_id").As(UnionAll(Select("p.id", "p.parent_id").From("accounts AS p").Where("p.id = 2"), // Show orders for account 2 and all its child accountsSelect("c.id", "c.parent_id").From("accounts AS c").Join("source_accounts AS sa", "c.parent_id = sa.id"),),),).Select("o.id", "o.date", "o.amount").From("orders AS o").Join("source_accounts", "o.account_id = source_accounts.id")fmt.Println(sb)Output:WITH RECURSIVE source_accounts (id, parent_id) AS ((SELECT p.id, p.parent_id FROM accounts AS p WHERE p.id = 2) UNION ALL (SELECT c.id, c.parent_id FROM accounts AS c JOIN source_accounts AS sa ON c.parent_id = sa.id)) SELECT o.id, o.date, o.amount FROM orders AS o JOIN source_accounts ON o.account_id = source_accounts.id
func (*CTEBuilder)Build¶added inv1.28.0
func (cteb *CTEBuilder) Build() (sqlstring, args []interface{})
Build returns compiled CTE string and args.
func (*CTEBuilder)BuildWithFlavor¶added inv1.28.0
func (cteb *CTEBuilder) BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})
BuildWithFlavor builds a CTE with the specified flavor and initial arguments.
func (*CTEBuilder)Clone¶added inv1.37.0
func (cteb *CTEBuilder) Clone() *CTEBuilder
Clone returns a deep copy of CTEBuilder.It's useful when you want to create a base builder and clone it to build similar queries.
func (*CTEBuilder)DeleteFrom¶added inv1.29.0
func (cteb *CTEBuilder) DeleteFrom(tablestring) *DeleteBuilder
DeleteFrom creates a new DeleteBuilder to build a DELETE statement using this CTE.
func (*CTEBuilder)Flavor¶added inv1.32.0
func (cteb *CTEBuilder) Flavor()Flavor
Flavor returns flavor of builder
func (*CTEBuilder)SQL¶added inv1.28.0
func (cteb *CTEBuilder) SQL(sqlstring) *CTEBuilder
SQL adds an arbitrary sql to current position.
func (*CTEBuilder)Select¶added inv1.28.0
func (cteb *CTEBuilder) Select(col ...string) *SelectBuilder
Select creates a new SelectBuilder to build a SELECT statement using this CTE.
func (*CTEBuilder)SetFlavor¶added inv1.28.0
func (cteb *CTEBuilder) SetFlavor(flavorFlavor) (oldFlavor)
SetFlavor sets the flavor of compiled sql.
func (*CTEBuilder)String¶added inv1.28.0
func (cteb *CTEBuilder) String()string
String returns the compiled CTE string.
func (*CTEBuilder)TableNames¶added inv1.28.0
func (cteb *CTEBuilder) TableNames() []string
TableNames returns all table names in a CTE.
func (*CTEBuilder)Update¶added inv1.29.0
func (cteb *CTEBuilder) Update(tablestring) *UpdateBuilder
Update creates a new UpdateBuilder to build an UPDATE statement using this CTE.
func (*CTEBuilder)With¶added inv1.28.0
func (cteb *CTEBuilder) With(queries ...*CTEQueryBuilder) *CTEBuilder
With sets the CTE name and columns.
func (*CTEBuilder)WithRecursive¶added inv1.29.0
func (cteb *CTEBuilder) WithRecursive(queries ...*CTEQueryBuilder) *CTEBuilder
WithRecursive sets the CTE name and columns and turns on the RECURSIVE keyword.
typeCTEQueryBuilder¶added inv1.29.0
type CTEQueryBuilder struct {// contains filtered or unexported fields}CTEQueryBuilder is a builder to build one table in CTE (Common Table Expression).
funcCTEQuery¶added inv1.29.0
func CTEQuery(namestring, cols ...string) *CTEQueryBuilder
CTEQuery creates a new CTE query builder with default flavor.
funcCTETable¶added inv1.28.0
func CTETable(namestring, cols ...string) *CTEQueryBuilder
CTETable creates a new CTE query builder with default flavor, marking it as a table.
The resulting CTE query can be used in a `SelectBuilder“, where its table name will beautomatically included in the FROM clause.
func (*CTEQueryBuilder)AddToTableList¶added inv1.29.0
func (ctetb *CTEQueryBuilder) AddToTableList() *CTEQueryBuilder
AddToTableList sets flag to add table name to table list in FROM clause of SELECT statement.
func (*CTEQueryBuilder)As¶added inv1.29.0
func (ctetb *CTEQueryBuilder) As(builderBuilder) *CTEQueryBuilder
As sets the builder to select data.
func (*CTEQueryBuilder)Build¶added inv1.29.0
func (ctetb *CTEQueryBuilder) Build() (sqlstring, args []interface{})
Build returns compiled CTE string and args.
func (*CTEQueryBuilder)BuildWithFlavor¶added inv1.29.0
func (ctetb *CTEQueryBuilder) BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})
BuildWithFlavor builds a CTE with the specified flavor and initial arguments.
func (*CTEQueryBuilder)Clone¶added inv1.37.0
func (ctetb *CTEQueryBuilder) Clone() *CTEQueryBuilder
Clone returns a deep copy of CTEQueryBuilder.It's useful when you want to create a base builder and clone it to build similar queries.
func (*CTEQueryBuilder)Flavor¶added inv1.32.0
func (ctetb *CTEQueryBuilder) Flavor()Flavor
Flavor returns flavor of builder
func (*CTEQueryBuilder)SQL¶added inv1.29.0
func (ctetb *CTEQueryBuilder) SQL(sqlstring) *CTEQueryBuilder
SQL adds an arbitrary sql to current position.
func (*CTEQueryBuilder)SetFlavor¶added inv1.29.0
func (ctetb *CTEQueryBuilder) SetFlavor(flavorFlavor) (oldFlavor)
SetFlavor sets the flavor of compiled sql.
func (*CTEQueryBuilder)ShouldAddToTableList¶added inv1.29.0
func (ctetb *CTEQueryBuilder) ShouldAddToTableList()bool
ShouldAddToTableList returns flag to add table name to table list in FROM clause of SELECT statement.
func (*CTEQueryBuilder)String¶added inv1.29.0
func (ctetb *CTEQueryBuilder) String()string
String returns the compiled CTE string.
func (*CTEQueryBuilder)Table¶added inv1.29.0
func (ctetb *CTEQueryBuilder) Table(namestring, cols ...string) *CTEQueryBuilder
Table sets the table name and columns in a CTE table.
func (*CTEQueryBuilder)TableName¶added inv1.29.0
func (ctetb *CTEQueryBuilder) TableName()string
TableName returns the CTE table name.
typeCTETableBuilderdeprecatedadded inv1.28.0
type CTETableBuilder =CTEQueryBuilder
CTETableBuilder is an alias of CTEQueryBuilder for backward compatibility.
Deprecated: use CTEQueryBuilder instead.
typeCond¶
type Cond struct {Args *Args}Cond provides several helper methods to build conditions.
func (*Cond)And¶added inv1.1.0
And is used to construct the expression AND logic like "expr1 AND expr2 AND expr3".
func (*Cond)GreaterEqualThan¶
GreaterEqualThan is used to construct the expression "field >= value".
func (*Cond)GreaterThan¶
GreaterThan is used to construct the expression "field > value".
func (*Cond)ILike¶added inv1.28.0
ILike is used to construct the expression "field ILIKE value".
When the database system does not support the ILIKE operator,the ILike method will return "LOWER(field) LIKE LOWER(value)"to simulate the behavior of the ILIKE operator.
func (*Cond)IsDistinctFrom¶added inv1.30.0
IsDistinctFrom is used to construct the expression "field IS DISTINCT FROM value".
When the database system does not support the IS DISTINCT FROM operator,the NotILike method will return "NOT field <=> value" for MySQL or a"CASE ... WHEN ... ELSE ... END" expression to simulate the behavior ofthe IS DISTINCT FROM operator.
func (*Cond)IsNotDistinctFrom¶added inv1.30.0
IsNotDistinctFrom is used to construct the expression "field IS NOT DISTINCT FROM value".
When the database system does not support the IS NOT DISTINCT FROM operator,the NotILike method will return "field <=> value" for MySQL or a"CASE ... WHEN ... ELSE ... END" expression to simulate the behavior ofthe IS NOT DISTINCT FROM operator.
func (*Cond)LessEqualThan¶
LessEqualThan is used to construct the expression "field <= value".
func (*Cond)NotBetween¶
NotBetween is used to construct the expression "field NOT BETWEEN lower AND upper".
func (*Cond)NotExists¶added inv1.21.0
NotExists is used to construct the expression "NOT EXISTS (subquery)".
func (*Cond)NotILike¶added inv1.29.1
NotILike is used to construct the expression "field NOT ILIKE value".
When the database system does not support the ILIKE operator,the NotILike method will return "LOWER(field) NOT LIKE LOWER(value)"to simulate the behavior of the ILIKE operator.
typeCreateTableBuilder¶added inv1.3.0
type CreateTableBuilder struct {// contains filtered or unexported fields}CreateTableBuilder is a builder to build CREATE TABLE.
Example¶
ctb := NewCreateTableBuilder()ctb.CreateTable("demo.user").IfNotExists()ctb.Define("id", "BIGINT(20)", "NOT NULL", "AUTO_INCREMENT", "PRIMARY KEY", `COMMENT "user id"`)ctb.Define("name", "VARCHAR(255)", "NOT NULL", `COMMENT "user name"`)ctb.Define("created_at", "DATETIME", "NOT NULL", `COMMENT "user create time"`)ctb.Define("modified_at", "DATETIME", "NOT NULL", `COMMENT "user modify time"`)ctb.Define("KEY", "idx_name_modified_at", "name, modified_at")ctb.Option("DEFAULT CHARACTER SET", "utf8mb4")fmt.Println(ctb)Output:CREATE TABLE IF NOT EXISTS demo.user (id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT "user id", name VARCHAR(255) NOT NULL COMMENT "user name", created_at DATETIME NOT NULL COMMENT "user create time", modified_at DATETIME NOT NULL COMMENT "user modify time", KEY idx_name_modified_at name, modified_at) DEFAULT CHARACTER SET utf8mb4
Example (TempTable)¶
ctb := NewCreateTableBuilder()ctb.CreateTempTable("demo.user").IfNotExists()ctb.Define("id", "BIGINT(20)", "NOT NULL", "AUTO_INCREMENT", "PRIMARY KEY", `COMMENT "user id"`)ctb.Define("name", "VARCHAR(255)", "NOT NULL", `COMMENT "user name"`)ctb.Define("created_at", "DATETIME", "NOT NULL", `COMMENT "user create time"`)ctb.Define("modified_at", "DATETIME", "NOT NULL", `COMMENT "user modify time"`)ctb.Define("KEY", "idx_name_modified_at", "name, modified_at")ctb.Option("DEFAULT CHARACTER SET", "utf8mb4")fmt.Println(ctb)Output:CREATE TEMPORARY TABLE IF NOT EXISTS demo.user (id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT "user id", name VARCHAR(255) NOT NULL COMMENT "user name", created_at DATETIME NOT NULL COMMENT "user create time", modified_at DATETIME NOT NULL COMMENT "user modify time", KEY idx_name_modified_at name, modified_at) DEFAULT CHARACTER SET utf8mb4
funcCreateTable¶added inv1.11.0
func CreateTable(tablestring) *CreateTableBuilder
CreateTable sets the table name in CREATE TABLE.
Example¶
sql := CreateTable("demo.user").IfNotExists().Define("id", "BIGINT(20)", "NOT NULL", "AUTO_INCREMENT", "PRIMARY KEY", `COMMENT "user id"`).String()fmt.Println(sql)Output:CREATE TABLE IF NOT EXISTS demo.user (id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT "user id")
funcNewCreateTableBuilder¶added inv1.3.0
func NewCreateTableBuilder() *CreateTableBuilder
NewCreateTableBuilder creates a new CREATE TABLE builder.
func (*CreateTableBuilder)Build¶added inv1.3.0
func (ctb *CreateTableBuilder) Build() (sqlstring, args []interface{})
Build returns compiled CREATE TABLE string and args.They can be used in `DB#Query` of package `database/sql` directly.
func (*CreateTableBuilder)BuildWithFlavor¶added inv1.3.0
func (ctb *CreateTableBuilder) BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})
BuildWithFlavor returns compiled CREATE TABLE string and args with flavor and initial args.They can be used in `DB#Query` of package `database/sql` directly.
func (*CreateTableBuilder)Clone¶added inv1.37.0
func (ctb *CreateTableBuilder) Clone() *CreateTableBuilder
Clone returns a deep copy of CreateTableBuilder.It's useful when you want to create a base builder and clone it to build similar queries.
func (*CreateTableBuilder)CreateTable¶added inv1.3.0
func (ctb *CreateTableBuilder) CreateTable(tablestring) *CreateTableBuilder
CreateTable sets the table name in CREATE TABLE.
func (*CreateTableBuilder)CreateTempTable¶added inv1.3.0
func (ctb *CreateTableBuilder) CreateTempTable(tablestring) *CreateTableBuilder
CreateTempTable sets the table name and changes the verb of ctb to CREATE TEMPORARY TABLE.
func (*CreateTableBuilder)Define¶added inv1.3.0
func (ctb *CreateTableBuilder) Define(def ...string) *CreateTableBuilder
Define adds definition of a column or index in CREATE TABLE.
func (*CreateTableBuilder)Flavor¶added inv1.32.0
func (ctb *CreateTableBuilder) Flavor()Flavor
Flavor returns flavor of builder
func (*CreateTableBuilder)IfNotExists¶added inv1.3.0
func (ctb *CreateTableBuilder) IfNotExists() *CreateTableBuilder
IfNotExists adds IF NOT EXISTS before table name in CREATE TABLE.
func (*CreateTableBuilder)NumDefine¶added inv1.25.0
func (ctb *CreateTableBuilder) NumDefine()int
NumDefine returns the number of definitions in CREATE TABLE.
Example¶
ctb := NewCreateTableBuilder()ctb.CreateTable("demo.user").IfNotExists()ctb.Define("id", "BIGINT(20)", "NOT NULL", "AUTO_INCREMENT", "PRIMARY KEY", `COMMENT "user id"`)ctb.Define("name", "VARCHAR(255)", "NOT NULL", `COMMENT "user name"`)ctb.Define("created_at", "DATETIME", "NOT NULL", `COMMENT "user create time"`)ctb.Define("modified_at", "DATETIME", "NOT NULL", `COMMENT "user modify time"`)ctb.Define("KEY", "idx_name_modified_at", "name, modified_at")ctb.Option("DEFAULT CHARACTER SET", "utf8mb4")// Count the number of definitions.fmt.Println(ctb.NumDefine())Output:5
func (*CreateTableBuilder)Option¶added inv1.3.0
func (ctb *CreateTableBuilder) Option(opt ...string) *CreateTableBuilder
Option adds a table option in CREATE TABLE.
func (*CreateTableBuilder)SQL¶added inv1.11.0
func (ctb *CreateTableBuilder) SQL(sqlstring) *CreateTableBuilder
SQL adds an arbitrary sql to current position.
Example¶
ctb := NewCreateTableBuilder()ctb.SQL(`/* before */`)ctb.CreateTempTable("demo.user").IfNotExists()ctb.SQL("/* after create */")ctb.Define("id", "BIGINT(20)", "NOT NULL", "AUTO_INCREMENT", "PRIMARY KEY", `COMMENT "user id"`)ctb.Define("name", "VARCHAR(255)", "NOT NULL", `COMMENT "user name"`)ctb.SQL("/* after define */")ctb.Option("DEFAULT CHARACTER SET", "utf8mb4")ctb.SQL(ctb.Var(Build("AS SELECT * FROM old.user WHERE name LIKE $?", "%Huan%")))sql, args := ctb.Build()fmt.Println(sql)fmt.Println(args)Output:/* before */ CREATE TEMPORARY TABLE IF NOT EXISTS demo.user /* after create */ (id BIGINT(20) NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT "user id", name VARCHAR(255) NOT NULL COMMENT "user name") /* after define */ DEFAULT CHARACTER SET utf8mb4 AS SELECT * FROM old.user WHERE name LIKE ?[%Huan%]
func (*CreateTableBuilder)SetFlavor¶added inv1.3.0
func (ctb *CreateTableBuilder) SetFlavor(flavorFlavor) (oldFlavor)
SetFlavor sets the flavor of compiled sql.
func (*CreateTableBuilder)String¶added inv1.3.0
func (ctb *CreateTableBuilder) String()string
String returns the compiled INSERT string.
func (*CreateTableBuilder)Var¶added inv1.11.0
func (ctb *CreateTableBuilder) Var(arg interface{})string
Var returns a placeholder for value.
typeDeleteBuilder¶
type DeleteBuilder struct {*WhereClauseCond// contains filtered or unexported fields}DeleteBuilder is a builder to build DELETE.
Example¶
db := NewDeleteBuilder()db.DeleteFrom("demo.user")db.Where(db.GreaterThan("id", 1234),db.Like("name", "%Du"),db.Or(db.IsNull("id_card"),db.In("status", 1, 2, 5),),"modified_at > created_at + "+db.Var(86400), // It's allowed to write arbitrary SQL.)sql, args := db.Build()fmt.Println(sql)fmt.Println(args)Output:DELETE FROM demo.user WHERE id > ? AND name LIKE ? AND (id_card IS NULL OR status IN (?, ?, ?)) AND modified_at > created_at + ?[1234 %Du 1 2 5 86400]
funcDeleteFrom¶added inv1.11.0
func DeleteFrom(table ...string) *DeleteBuilder
DeleteFrom sets table name in DELETE.
Example¶
sql := DeleteFrom("demo.user").Where("status = 1",).Limit(10).String()fmt.Println(sql)Output:DELETE FROM demo.user WHERE status = 1 LIMIT ?
funcNewDeleteBuilder¶
func NewDeleteBuilder() *DeleteBuilder
NewDeleteBuilder creates a new DELETE builder.
func (*DeleteBuilder)AddWhereClause¶added inv1.27.0
func (db *DeleteBuilder) AddWhereClause(whereClause *WhereClause) *DeleteBuilder
AddWhereClause adds all clauses in the whereClause to SELECT.
func (*DeleteBuilder)Ascdeprecatedadded inv1.11.0
func (db *DeleteBuilder) Asc() *DeleteBuilder
Asc sets order of ORDER BY to ASC.
Deprecated: Use OrderByAsc instead. Asc only supports a single direction for all ORDER BY columns.
func (*DeleteBuilder)Build¶
func (db *DeleteBuilder) Build() (sqlstring, args []interface{})
Build returns compiled DELETE string and args.They can be used in `DB#Query` of package `database/sql` directly.
func (*DeleteBuilder)BuildWithFlavor¶
func (db *DeleteBuilder) BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})
BuildWithFlavor returns compiled DELETE string and args with flavor and initial args.They can be used in `DB#Query` of package `database/sql` directly.
func (*DeleteBuilder)Clone¶added inv1.37.0
func (db *DeleteBuilder) Clone() *DeleteBuilder
Clone returns a deep copy of DeleteBuilder.It's useful when you want to create a base builder and clone it to build similar queries.
func (*DeleteBuilder)DeleteFrom¶
func (db *DeleteBuilder) DeleteFrom(table ...string) *DeleteBuilder
DeleteFrom sets table name in DELETE.
func (*DeleteBuilder)Descdeprecatedadded inv1.11.0
func (db *DeleteBuilder) Desc() *DeleteBuilder
Desc sets order of ORDER BY to DESC.
Deprecated: Use OrderByDesc instead. Desc only supports a single direction for all ORDER BY columns.
func (*DeleteBuilder)Flavor¶added inv1.32.0
func (db *DeleteBuilder) Flavor()Flavor
Flavor returns flavor of builder
func (*DeleteBuilder)Limit¶added inv1.11.0
func (db *DeleteBuilder) Limit(limitint) *DeleteBuilder
Limit sets the LIMIT in DELETE.
func (*DeleteBuilder)OrderBydeprecatedadded inv1.11.0
func (db *DeleteBuilder) OrderBy(col ...string) *DeleteBuilder
OrderBy sets columns of ORDER BY in DELETE.
Deprecated: Use OrderByAsc or OrderByDesc instead for better support of multiple ORDER BY columns with different directions.OrderBy combined with Asc/Desc only supports a single direction for all columns.
func (*DeleteBuilder)OrderByAsc¶added inv1.38.0
func (db *DeleteBuilder) OrderByAsc(colstring) *DeleteBuilder
OrderByAsc sets a column of ORDER BY in DELETE with ASC order.It supports chaining multiple calls to add multiple ORDER BY columns with different directions.
db.OrderByAsc("name").OrderByDesc("id")// Generates: ORDER BY name ASC, id DESCfunc (*DeleteBuilder)OrderByDesc¶added inv1.38.0
func (db *DeleteBuilder) OrderByDesc(colstring) *DeleteBuilder
OrderByDesc sets a column of ORDER BY in DELETE with DESC order.It supports chaining multiple calls to add multiple ORDER BY columns with different directions.
db.OrderByDesc("id").OrderByAsc("name")// Generates: ORDER BY id DESC, name ASCfunc (*DeleteBuilder)Returning¶added inv1.36.0
func (db *DeleteBuilder) Returning(col ...string) *DeleteBuilder
Returning sets returning columns.For DBMS that doesn't support RETURNING, e.g. MySQL, it will be ignored.
Example¶
db := NewDeleteBuilder()db.DeleteFrom("user")db.Where(db.Equal("id", 123))db.Returning("id", "deleted_at")sql, args := db.BuildWithFlavor(PostgreSQL)fmt.Println(sql)fmt.Println(args)Output:DELETE FROM user WHERE id = $1 RETURNING id, deleted_at[123]
func (*DeleteBuilder)SQL¶added inv1.11.0
func (db *DeleteBuilder) SQL(sqlstring) *DeleteBuilder
SQL adds an arbitrary sql to current position.
Example¶
db := NewDeleteBuilder()db.SQL(`/* before */`)db.DeleteFrom("demo.user")db.SQL("PARTITION (p0)")db.Where(db.GreaterThan("id", 1234),)db.SQL("/* after where */")db.OrderBy("id")db.SQL("/* after order by */")db.Limit(10)db.SQL("/* after limit */")sql, args := db.Build()fmt.Println(sql)fmt.Println(args)Output:/* before */ DELETE FROM demo.user PARTITION (p0) WHERE id > ? /* after where */ ORDER BY id /* after order by */ LIMIT ? /* after limit */[1234 10]
func (*DeleteBuilder)SetFlavor¶
func (db *DeleteBuilder) SetFlavor(flavorFlavor) (oldFlavor)
SetFlavor sets the flavor of compiled sql.
func (*DeleteBuilder)String¶
func (db *DeleteBuilder) String()string
String returns the compiled DELETE string.
func (*DeleteBuilder)TableNames¶added inv1.32.0
func (db *DeleteBuilder) TableNames() []string
TableNames returns all table names in this DELETE statement.
func (*DeleteBuilder)Where¶
func (db *DeleteBuilder) Where(andExpr ...string) *DeleteBuilder
Where sets expressions of WHERE in DELETE.
func (*DeleteBuilder)With¶added inv1.29.0
func (db *DeleteBuilder) With(builder *CTEBuilder) *DeleteBuilder
With sets WITH clause (the Common Table Expression) before DELETE.
Example¶
sql := With(CTEQuery("users").As(Select("id", "name").From("users").Where("name IS NULL"),),).DeleteFrom("orders").Where("users.id = orders.user_id",).String()fmt.Println(sql)Output:WITH users AS (SELECT id, name FROM users WHERE name IS NULL) DELETE FROM orders WHERE users.id = orders.user_id
typeFieldMapperFunc¶added inv1.12.0
FieldMapperFunc is a func to map struct field names to column names,which will be used in query as columns.
Example¶
type Orders struct {ID int64UserID int64ProductName stringStatus intUserAddrLine1 stringUserAddrLine2 stringCreatedAt time.Time}// Create a Struct for Orders.orders := NewStruct(new(Orders))// Set the default field mapper to snake_case mapper globally.DefaultFieldMapper = SnakeCaseMapper// Field names are converted to snake_case words.sql1, _ := orders.SelectFrom("orders").Limit(10).Build()fmt.Println(sql1)// Changing the default field mapper will *NOT* affect field names in orders.// Once field name conversion is done, they will not be changed again.DefaultFieldMapper = SomeOtherMappersql2, _ := orders.SelectFrom("orders").Limit(10).Build()fmt.Println(sql1 == sql2)Output:SELECT orders.id, orders.user_id, orders.product_name, orders.status, orders.user_addr_line1, orders.user_addr_line2, orders.created_at FROM orders LIMIT ?true
typeFlavor¶
type Flavorint
Flavor is the flag to control the format of compiled sql.
Example¶
// Create a flavored builder.sb := PostgreSQL.NewSelectBuilder()sb.Select("name").From("user").Where(sb.E("id", 1234),sb.G("rank", 3),)sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT name FROM user WHERE id = $1 AND rank > $2[1234 3]
const (MySQL FlavorPostgreSQLSQLiteSQLServerCQLClickHousePrestoOracleInformixDoris)
Supported flavors.
func (Flavor)Interpolate¶added inv1.4.0
Interpolate parses sql returned by `Args#Compile` or `Builder`,and interpolate args to replace placeholders in the sql.
If there are some args missing in sql, e.g. the number of placeholders are larger than len(args),returns ErrMissingArgs error.
Example (Cql)¶
sb := CQL.NewSelectBuilder()sb.Select("name").From("user").Where(sb.E("id", 1234),sb.E("name", "Charmy Liu"),)sql, args := sb.Build()query, err := CQL.Interpolate(sql, args)fmt.Println(query)fmt.Println(err)Output:SELECT name FROM user WHERE id = 1234 AND name = 'Charmy Liu'<nil>
Example (Infomix)¶
sb := Informix.NewSelectBuilder()sb.Select("name").From("user").Where(sb.NE("id", 1234),sb.E("name", "Charmy Liu"),sb.E("enabled", true),)sql, args := sb.Build()query, err := Informix.Interpolate(sql, args)fmt.Println(query)fmt.Println(err)Output:SELECT name FROM user WHERE id <> 1234 AND name = 'Charmy Liu' AND enabled = TRUE<nil>
Example (MySQL)¶
sb := MySQL.NewSelectBuilder()sb.Select("name").From("user").Where(sb.NE("id", 1234),sb.E("name", "Charmy Liu"),sb.Like("desc", "%mother's day%"),)sql, args := sb.Build()query, err := MySQL.Interpolate(sql, args)fmt.Println(query)fmt.Println(err)Output:SELECT name FROM user WHERE id <> 1234 AND name = 'Charmy Liu' AND desc LIKE '%mother\'s day%'<nil>
Example (Oracle)¶
sb := Oracle.NewSelectBuilder()sb.Select("name").From("user").Where(sb.E("id", 1234),sb.E("name", "Charmy Liu"),sb.E("enabled", true),)sql, args := sb.Build()query, err := Oracle.Interpolate(sql, args)fmt.Println(query)fmt.Println(err)Output:SELECT name FROM user WHERE id = 1234 AND name = 'Charmy Liu' AND enabled = 1<nil>
Example (PostgreSQL)¶
// Only the last `$1` is interpolated.// Others are not interpolated as they are inside dollar quote (the `$$`).query, err := PostgreSQL.Interpolate(`CREATE FUNCTION dup(in int, out f1 int, out f2 text) AS $$ SELECT $1, CAST($1 AS text) || ' is text'$$LANGUAGE SQL;SELECT * FROM dup($1);`, []interface{}{42})fmt.Println(query)fmt.Println(err)Output:CREATE FUNCTION dup(in int, out f1 int, out f2 text) AS $$ SELECT $1, CAST($1 AS text) || ' is text'$$LANGUAGE SQL;SELECT * FROM dup(42);<nil>
Example (SqlServer)¶
sb := SQLServer.NewSelectBuilder()sb.Select("name").From("user").Where(sb.NE("id", 1234),sb.E("name", "Charmy Liu"),sb.Like("desc", "%mother's day%"),)sql, args := sb.Build()query, err := SQLServer.Interpolate(sql, args)fmt.Println(query)fmt.Println(err)Output:SELECT name FROM user WHERE id <> 1234 AND name = N'Charmy Liu' AND desc LIKE N'%mother\'s day%'<nil>
Example (Sqlite)¶
sb := SQLite.NewSelectBuilder()sb.Select("name").From("user").Where(sb.NE("id", 1234),sb.E("name", "Charmy Liu"),sb.Like("desc", "%mother's day%"),)sql, args := sb.Build()query, err := SQLite.Interpolate(sql, args)fmt.Println(query)fmt.Println(err)Output:SELECT name FROM user WHERE id <> 1234 AND name = 'Charmy Liu' AND desc LIKE '%mother\'s day%'<nil>
func (Flavor)NewCTEBuilder¶added inv1.28.0
func (fFlavor) NewCTEBuilder() *CTEBuilder
NewCTEBuilder creates a new CTE builder with flavor.
func (Flavor)NewCTEQueryBuilder¶added inv1.29.0
func (fFlavor) NewCTEQueryBuilder() *CTEQueryBuilder
NewCTETableBuilder creates a new CTE table builder with flavor.
func (Flavor)NewCreateTableBuilder¶added inv1.3.0
func (fFlavor) NewCreateTableBuilder() *CreateTableBuilder
NewCreateTableBuilder creates a new CREATE TABLE builder with flavor.
func (Flavor)NewDeleteBuilder¶
func (fFlavor) NewDeleteBuilder() *DeleteBuilder
NewDeleteBuilder creates a new DELETE builder with flavor.
func (Flavor)NewInsertBuilder¶
func (fFlavor) NewInsertBuilder() *InsertBuilder
NewInsertBuilder creates a new INSERT builder with flavor.
func (Flavor)NewSelectBuilder¶
func (fFlavor) NewSelectBuilder() *SelectBuilder
NewSelectBuilder creates a new SELECT builder with flavor.
func (Flavor)NewUnionBuilder¶added inv1.11.0
func (fFlavor) NewUnionBuilder() *UnionBuilder
NewUnionBuilder creates a new UNION builder with flavor.
func (Flavor)NewUpdateBuilder¶
func (fFlavor) NewUpdateBuilder() *UpdateBuilder
NewUpdateBuilder creates a new UPDATE builder with flavor.
func (Flavor)PrepareInsertIgnore¶added inv1.16.0
func (fFlavor) PrepareInsertIgnore(tablestring, ib *InsertBuilder)
PrepareInsertIgnore prepares the insert builder to build insert ignore SQL statement based on the sql flavor
typeGetAliasFunc¶added inv1.23.0
type GetAliasFunc func(field *reflect.StructField) (aliasstring, dbtagstring)
GetAliasFunc is a func to get alias and dbtag
typeInsertBuilder¶
type InsertBuilder struct {// contains filtered or unexported fields}InsertBuilder is a builder to build INSERT.
Example¶
ib := NewInsertBuilder()ib.InsertInto("demo.user")ib.Cols("id", "name", "status", "created_at", "updated_at")ib.Values(1, "Huan Du", 1, Raw("UNIX_TIMESTAMP(NOW())"))ib.Values(2, "Charmy Liu", 1, 1234567890)sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:INSERT INTO demo.user (id, name, status, created_at, updated_at) VALUES (?, ?, ?, UNIX_TIMESTAMP(NOW())), (?, ?, ?, ?)[1 Huan Du 1 2 Charmy Liu 1 1234567890]
Example (FlavorOracle)¶
ib := Oracle.NewInsertBuilder()ib.InsertInto("demo.user")ib.Cols("id", "name", "status")ib.Values(1, "Huan Du", 1)ib.Values(2, "Charmy Liu", 1)sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:INSERT ALL INTO demo.user (id, name, status) VALUES (:1, :2, :3) INTO demo.user (id, name, status) VALUES (:4, :5, :6) SELECT 1 from DUAL[1 Huan Du 1 2 Charmy Liu 1]
Example (InsertIgnore)¶
ib := NewInsertBuilder()ib.InsertIgnoreInto("demo.user")ib.Cols("id", "name", "status", "created_at", "updated_at")ib.Values(1, "Huan Du", 1, Raw("UNIX_TIMESTAMP(NOW())"))ib.Values(2, "Charmy Liu", 1, 1234567890)sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:INSERT IGNORE INTO demo.user (id, name, status, created_at, updated_at) VALUES (?, ?, ?, UNIX_TIMESTAMP(NOW())), (?, ?, ?, ?)[1 Huan Du 1 2 Charmy Liu 1 1234567890]
Example (InsertIgnore_clickhouse)¶
ib := ClickHouse.NewInsertBuilder()ib.InsertIgnoreInto("demo.user")ib.Cols("id", "name", "status", "created_at")ib.Values(1, "Huan Du", 1, Raw("UNIX_TIMESTAMP(NOW())"))ib.Values(2, "Charmy Liu", 1, 1234567890)sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:INSERT INTO demo.user (id, name, status, created_at) VALUES (?, ?, ?, UNIX_TIMESTAMP(NOW())), (?, ?, ?, ?)[1 Huan Du 1 2 Charmy Liu 1 1234567890]
Example (InsertIgnore_postgres)¶
ib := PostgreSQL.NewInsertBuilder()ib.InsertIgnoreInto("demo.user")ib.Cols("id", "name", "status", "created_at")ib.Values(1, "Huan Du", 1, Raw("UNIX_TIMESTAMP(NOW())"))ib.Values(2, "Charmy Liu", 1, 1234567890)sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:INSERT INTO demo.user (id, name, status, created_at) VALUES ($1, $2, $3, UNIX_TIMESTAMP(NOW())), ($4, $5, $6, $7) ON CONFLICT DO NOTHING[1 Huan Du 1 2 Charmy Liu 1 1234567890]
Example (InsertIgnore_sqlite)¶
ib := SQLite.NewInsertBuilder()ib.InsertIgnoreInto("demo.user")ib.Cols("id", "name", "status", "created_at")ib.Values(1, "Huan Du", 1, Raw("UNIX_TIMESTAMP(NOW())"))ib.Values(2, "Charmy Liu", 1, 1234567890)sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:INSERT OR IGNORE INTO demo.user (id, name, status, created_at) VALUES (?, ?, ?, UNIX_TIMESTAMP(NOW())), (?, ?, ?, ?)[1 Huan Du 1 2 Charmy Liu 1 1234567890]
Example (ReplaceInto)¶
ib := NewInsertBuilder()ib.ReplaceInto("demo.user")ib.Cols("id", "name", "status", "created_at", "updated_at")ib.Values(1, "Huan Du", 1, Raw("UNIX_TIMESTAMP(NOW())"))ib.Values(2, "Charmy Liu", 1, 1234567890)sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:REPLACE INTO demo.user (id, name, status, created_at, updated_at) VALUES (?, ?, ?, UNIX_TIMESTAMP(NOW())), (?, ?, ?, ?)[1 Huan Du 1 2 Charmy Liu 1 1234567890]
Example (SubSelect)¶
ib := NewInsertBuilder()ib.InsertInto("demo.user")ib.Cols("id", "name")sb := ib.Select("id", "name").From("demo.test")sb.Where(sb.EQ("id", 1))sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:INSERT INTO demo.user (id, name) SELECT id, name FROM demo.test WHERE id = ?[1]
Example (SubSelect_informix)¶
ib := Informix.NewInsertBuilder()ib.InsertInto("demo.user")ib.Cols("id", "name")sb := ib.Select("id", "name").From("demo.test")sb.Where(sb.EQ("id", 1))sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:INSERT INTO demo.user (id, name) SELECT id, name FROM demo.test WHERE id = ?[1]
Example (SubSelect_oracle)¶
ib := Oracle.NewInsertBuilder()ib.InsertInto("demo.user")ib.Cols("id", "name")sb := ib.Select("id", "name").From("demo.test")sb.Where(sb.EQ("id", 1))sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:INSERT INTO demo.user (id, name) SELECT id, name FROM demo.test WHERE id = :1[1]
funcInsertIgnoreInto¶added inv1.11.0
func InsertIgnoreInto(tablestring) *InsertBuilder
InsertIgnoreInto sets table name in INSERT IGNORE.
Example¶
sql, args := InsertIgnoreInto("demo.user").Cols("id", "name", "status").Values(4, "Sample", 2).Build()fmt.Println(sql)fmt.Println(args)Output:INSERT IGNORE INTO demo.user (id, name, status) VALUES (?, ?, ?)[4 Sample 2]
funcInsertInto¶added inv1.11.0
func InsertInto(tablestring) *InsertBuilder
InsertInto sets table name in INSERT.
Example¶
sql, args := InsertInto("demo.user").Cols("id", "name", "status").Values(4, "Sample", 2).Build()fmt.Println(sql)fmt.Println(args)Output:INSERT INTO demo.user (id, name, status) VALUES (?, ?, ?)[4 Sample 2]
funcNewInsertBuilder¶
func NewInsertBuilder() *InsertBuilder
NewInsertBuilder creates a new INSERT builder.
funcReplaceInto¶added inv1.11.0
func ReplaceInto(tablestring) *InsertBuilder
ReplaceInto sets table name and changes the verb of ib to REPLACE.REPLACE INTO is a MySQL extension to the SQL standard.
Example¶
sql, args := ReplaceInto("demo.user").Cols("id", "name", "status").Values(4, "Sample", 2).Build()fmt.Println(sql)fmt.Println(args)Output:REPLACE INTO demo.user (id, name, status) VALUES (?, ?, ?)[4 Sample 2]
func (*InsertBuilder)Build¶
func (ib *InsertBuilder) Build() (sqlstring, args []interface{})
Build returns compiled INSERT string and args.They can be used in `DB#Query` of package `database/sql` directly.
func (*InsertBuilder)BuildWithFlavor¶
func (ib *InsertBuilder) BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})
BuildWithFlavor returns compiled INSERT string and args with flavor and initial args.They can be used in `DB#Query` of package `database/sql` directly.
func (*InsertBuilder)Clone¶added inv1.37.0
func (ib *InsertBuilder) Clone() *InsertBuilder
Clone returns a deep copy of InsertBuilder.It's useful when you want to create a base builder and clone it to build similar queries.
func (*InsertBuilder)Cols¶
func (ib *InsertBuilder) Cols(col ...string) *InsertBuilder
Cols sets columns in INSERT.
func (*InsertBuilder)Flavor¶added inv1.32.0
func (ib *InsertBuilder) Flavor()Flavor
Flavor returns flavor of builder
func (*InsertBuilder)InsertIgnoreInto¶added inv1.5.0
func (ib *InsertBuilder) InsertIgnoreInto(tablestring) *InsertBuilder
InsertIgnoreInto sets table name in INSERT IGNORE.
func (*InsertBuilder)InsertInto¶
func (ib *InsertBuilder) InsertInto(tablestring) *InsertBuilder
InsertInto sets table name in INSERT.
func (*InsertBuilder)NumValue¶added inv1.25.0
func (ib *InsertBuilder) NumValue()int
NumValue returns the number of values to insert.
Example¶
ib := NewInsertBuilder()ib.InsertInto("demo.user")ib.Cols("id", "name")ib.Values(1, "Huan Du")ib.Values(2, "Charmy Liu")// Count the number of values.fmt.Println(ib.NumValue())Output:2
func (*InsertBuilder)ReplaceInto¶added inv1.3.0
func (ib *InsertBuilder) ReplaceInto(tablestring) *InsertBuilder
ReplaceInto sets table name and changes the verb of ib to REPLACE.REPLACE INTO is a MySQL extension to the SQL standard.
func (*InsertBuilder)Returning¶added inv1.34.0
func (ib *InsertBuilder) Returning(col ...string) *InsertBuilder
Returning sets returning columns.For DBMS that doesn't support RETURNING, e.g. MySQL, it will be ignored.
Example¶
sql, args := InsertInto("user").Cols("name").Values("Huan Du").Returning("id").BuildWithFlavor(PostgreSQL)fmt.Println(sql)fmt.Println(args)Output:INSERT INTO user (name) VALUES ($1) RETURNING id[Huan Du]
func (*InsertBuilder)SQL¶added inv1.11.0
func (ib *InsertBuilder) SQL(sqlstring) *InsertBuilder
SQL adds an arbitrary sql to current position.
Example¶
ib := NewInsertBuilder()ib.SQL("/* before */")ib.InsertInto("demo.user")ib.SQL("PARTITION (p0)")ib.Cols("id", "name", "status", "created_at")ib.SQL("/* after cols */")ib.Values(3, "Shawn Du", 1, 1234567890)ib.SQL(ib.Var(Build("ON DUPLICATE KEY UPDATE status = $?", 1)))sql, args := ib.Build()fmt.Println(sql)fmt.Println(args)Output:/* before */ INSERT INTO demo.user PARTITION (p0) (id, name, status, created_at) /* after cols */ VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE status = ?[3 Shawn Du 1 1234567890 1]
func (*InsertBuilder)Select¶added inv1.24.0
func (isb *InsertBuilder) Select(col ...string) *SelectBuilder
Select returns a new SelectBuilder to build a SELECT statement inside the INSERT INTO.
func (*InsertBuilder)SetFlavor¶
func (ib *InsertBuilder) SetFlavor(flavorFlavor) (oldFlavor)
SetFlavor sets the flavor of compiled sql.
func (*InsertBuilder)String¶
func (ib *InsertBuilder) String()string
String returns the compiled INSERT string.
func (*InsertBuilder)Values¶
func (ib *InsertBuilder) Values(value ...interface{}) *InsertBuilder
Values adds a list of values for a row in INSERT.
func (*InsertBuilder)Var¶added inv1.11.0
func (ib *InsertBuilder) Var(arg interface{})string
Var returns a placeholder for value.
typeJoinOption¶added inv1.1.0
type JoinOptionstring
JoinOption is the option in JOIN.
const (FullJoinJoinOption = "FULL"FullOuterJoinJoinOption = "FULL OUTER"InnerJoinJoinOption = "INNER"LeftJoinJoinOption = "LEFT"LeftOuterJoinJoinOption = "LEFT OUTER"RightJoinJoinOption = "RIGHT"RightOuterJoinJoinOption = "RIGHT OUTER")
Join options.
typeSelectBuilder¶
type SelectBuilder struct {*WhereClauseCond// contains filtered or unexported fields}SelectBuilder is a builder to build SELECT.
Example¶
sb := NewSelectBuilder()sb.Distinct().Select("id", "name", sb.As("COUNT(*)", "t"))sb.From("demo.user")sb.Where(sb.GreaterThan("id", 1234),sb.Like("name", "%Du"),sb.Or(sb.IsNull("id_card"),sb.In("status", 1, 2, 5),),sb.NotIn("id",NewSelectBuilder().Select("id").From("banned"),), // Nested SELECT."modified_at > created_at + "+sb.Var(86400), // It's allowed to write arbitrary SQL.)sb.GroupBy("status").Having(sb.NotIn("status", 4, 5))sb.OrderByAsc("modified_at")sb.Limit(10).Offset(5)s, args := sb.Build()fmt.Println(s)fmt.Println(args)Output:SELECT DISTINCT id, name, COUNT(*) AS t FROM demo.user WHERE id > ? AND name LIKE ? AND (id_card IS NULL OR status IN (?, ?, ?)) AND id NOT IN (SELECT id FROM banned) AND modified_at > created_at + ? GROUP BY status HAVING status NOT IN (?, ?) ORDER BY modified_at ASC LIMIT ? OFFSET ?[1234 %Du 1 2 5 86400 4 5 10 5]
Example (AdvancedUsage)¶
sb := NewSelectBuilder()innerSb := NewSelectBuilder()// Named arguments are supported.start := sql.Named("start", 1234567890)end := sql.Named("end", 1234599999)level := sql.Named("level", 20)sb.Select("id", "name")sb.From(sb.BuilderAs(innerSb, "user"),)sb.Where(sb.In("status", Flatten([]int{1, 2, 3})...),sb.Between("created_at", start, end),)sb.OrderByDesc("modified_at")innerSb.Select("*")innerSb.From("banned")innerSb.Where(innerSb.GreaterThan("level", level),innerSb.LessEqualThan("updated_at", end),innerSb.NotIn("name", Flatten([]string{"Huan Du", "Charmy Liu"})...),)s, args := sb.Build()fmt.Println(s)fmt.Println(args)Output:SELECT id, name FROM (SELECT * FROM banned WHERE level > @level AND updated_at <= @end AND name NOT IN (?, ?)) AS user WHERE status IN (?, ?, ?) AND created_at BETWEEN @start AND @end ORDER BY modified_at DESC[Huan Du Charmy Liu 1 2 3 {{} level 20} {{} end 1234599999} {{} start 1234567890}]
Example (CustomSELECT)¶
Example for issue #115.
sb := NewSelectBuilder()// Set a custom SELECT clause.sb.SQL("SELECT id, name FROM user").Where(sb.In("id", 1, 2, 3),)s, args := sb.Build()fmt.Println(s)fmt.Println(args)Output:SELECT id, name FROM user WHERE id IN (?, ?, ?)[1 2 3]
Example (Join)¶
sb := NewSelectBuilder()sb.Select("u.id", "u.name", "c.type", "p.nickname")sb.From("user u")sb.Join("contract c","u.id = c.user_id",sb.In("c.status", 1, 2, 5),)sb.JoinWithOption(RightOuterJoin, "person p","u.id = p.user_id",sb.Like("p.surname", "%Du"),)sb.Where("u.modified_at > u.created_at + " + sb.Var(86400), // It's allowed to write arbitrary SQL.)sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT u.id, u.name, c.type, p.nickname FROM user u JOIN contract c ON u.id = c.user_id AND c.status IN (?, ?, ?) RIGHT OUTER JOIN person p ON u.id = p.user_id AND p.surname LIKE ? WHERE u.modified_at > u.created_at + ?[1 2 5 %Du 86400]
Example (Limit_offset)¶
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, ClickHouse, Presto, Oracle, Informix, Doris}results := make([][]string, len(flavors))sb := NewSelectBuilder()saveResults := func() {for i, f := range flavors {s, _ := sb.BuildWithFlavor(f)results[i] = append(results[i], s)}}sb.Select("*")sb.From("user")// Case #1: limit < 0 and offset < 0//// All: No limit or offset in query.sb.Limit(-1)sb.Offset(-1)saveResults()// Case #2: limit < 0 and offset >= 0//// MySQL and SQLite: Ignore offset if the limit is not set.// PostgreSQL: Offset can be set without limit.// SQLServer: Offset can be set without limit.// CQL: Ignore offset.// Oracle: Offset can be set without limit.sb.Limit(-1)sb.Offset(0)saveResults()// Case #3: limit >= 0 and offset >= 0//// CQL: Ignore offset.// All others: Set both limit and offset.sb.Limit(1)sb.Offset(0)saveResults()// Case #4: limit >= 0 and offset < 0//// All: Set limit in query.sb.Limit(1)sb.Offset(-1)saveResults()// Case #5: limit >= 0 and offset >= 0 order by id//// CQL: Ignore offset.// All others: Set both limit and offset.sb.Limit(1)sb.Offset(1)sb.OrderBy("id")saveResults()for i, result := range results {fmt.Println()fmt.Println(flavors[i])for n, s := range result {fmt.Printf("#%d: %s\n", n+1, s)}}Output:MySQL#1: SELECT * FROM user#2: SELECT * FROM user#3: SELECT * FROM user LIMIT ? OFFSET ?#4: SELECT * FROM user LIMIT ?#5: SELECT * FROM user ORDER BY id LIMIT ? OFFSET ?PostgreSQL#1: SELECT * FROM user#2: SELECT * FROM user OFFSET $1#3: SELECT * FROM user LIMIT $1 OFFSET $2#4: SELECT * FROM user LIMIT $1#5: SELECT * FROM user ORDER BY id LIMIT $1 OFFSET $2SQLite#1: SELECT * FROM user#2: SELECT * FROM user#3: SELECT * FROM user LIMIT ? OFFSET ?#4: SELECT * FROM user LIMIT ?#5: SELECT * FROM user ORDER BY id LIMIT ? OFFSET ?SQLServer#1: SELECT * FROM user#2: SELECT * FROM user ORDER BY 1 OFFSET @p1 ROWS#3: SELECT * FROM user ORDER BY 1 OFFSET @p1 ROWS FETCH NEXT @p2 ROWS ONLY#4: SELECT * FROM user ORDER BY 1 OFFSET 0 ROWS FETCH NEXT @p1 ROWS ONLY#5: SELECT * FROM user ORDER BY id OFFSET @p1 ROWS FETCH NEXT @p2 ROWS ONLYCQL#1: SELECT * FROM user#2: SELECT * FROM user#3: SELECT * FROM user LIMIT ?#4: SELECT * FROM user LIMIT ?#5: SELECT * FROM user ORDER BY id LIMIT ?ClickHouse#1: SELECT * FROM user#2: SELECT * FROM user#3: SELECT * FROM user LIMIT ? OFFSET ?#4: SELECT * FROM user LIMIT ?#5: SELECT * FROM user ORDER BY id LIMIT ? OFFSET ?Presto#1: SELECT * FROM user#2: SELECT * FROM user OFFSET ?#3: SELECT * FROM user OFFSET ? LIMIT ?#4: SELECT * FROM user LIMIT ?#5: SELECT * FROM user ORDER BY id OFFSET ? LIMIT ?Oracle#1: SELECT * FROM user#2: SELECT * FROM (SELECT ROWNUM r, * FROM (SELECT * FROM user) user) WHERE r >= :1 + 1#3: SELECT * FROM (SELECT ROWNUM r, * FROM (SELECT * FROM user) user) WHERE r BETWEEN :1 + 1 AND :2 + :3#4: SELECT * FROM (SELECT ROWNUM r, * FROM (SELECT * FROM user) user) WHERE r BETWEEN 1 AND :1#5: SELECT * FROM (SELECT ROWNUM r, * FROM (SELECT * FROM user ORDER BY id) user) WHERE r BETWEEN :1 + 1 AND :2 + :3Informix#1: SELECT * FROM user#2: SELECT * FROM user#3: SELECT * FROM user SKIP ? FIRST ?#4: SELECT * FROM user FIRST ?#5: SELECT * FROM user ORDER BY id SKIP ? FIRST ?Doris#1: SELECT * FROM user#2: SELECT * FROM user#3: SELECT * FROM user LIMIT 1 OFFSET 0#4: SELECT * FROM user LIMIT 1#5: SELECT * FROM user ORDER BY id LIMIT 1 OFFSET 1
Example (NestedJoin)¶
sb := NewSelectBuilder()nestedSb := NewSelectBuilder()// Build the nested subquerynestedSb.Select("b.id", "b.user_id")nestedSb.From("users2 AS b")nestedSb.Where(nestedSb.GreaterThan("b.age", 20))// Build the main query with nested joinsb.Select("a.id", "a.user_id")sb.From("users AS a")sb.Join(sb.BuilderAs(nestedSb, "b"),"a.user_id = b.user_id",)sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT a.id, a.user_id FROM users AS a JOIN (SELECT b.id, b.user_id FROM users2 AS b WHERE b.age > ?) AS b ON a.user_id = b.user_id[20]
Example (VarInCols)¶
// Column name may contain some characters, e.g. the $ sign, which have special meanings in builders.// It's recommended to call Escape() or EscapeAll() to escape the name.sb := NewSelectBuilder()v := sb.Var("foo")sb.Select(Escape("colHasA$Sign"), v)sb.From("table")s, args := sb.Build()fmt.Println(s)fmt.Println(args)Output:SELECT colHasA$Sign, ? FROM table[foo]
funcNewSelectBuilder¶
func NewSelectBuilder() *SelectBuilder
NewSelectBuilder creates a new SELECT builder.
funcSelect¶added inv1.11.0
func Select(col ...string) *SelectBuilder
Select sets columns in SELECT.
Example¶
// Build a SQL to create a HIVE table using MySQL-like SQL syntax.sql, args := Select("columns[0] id", "columns[1] name", "columns[2] year").From(MySQL.Quote("all-users.csv")).Limit(100).Build()fmt.Println(sql)fmt.Println(args)Output:SELECT columns[0] id, columns[1] name, columns[2] year FROM `all-users.csv` LIMIT ?[100]
func (*SelectBuilder)AddWhereClause¶added inv1.27.0
func (sb *SelectBuilder) AddWhereClause(whereClause *WhereClause) *SelectBuilder
AddWhereClause adds all clauses in the whereClause to SELECT.
func (*SelectBuilder)As¶
func (sb *SelectBuilder) As(name, aliasstring)string
As returns an AS expression.
func (*SelectBuilder)Ascdeprecated
func (sb *SelectBuilder) Asc() *SelectBuilder
Asc sets order of ORDER BY to ASC.
Deprecated: Use OrderByAsc instead. Asc only supports a single direction for all ORDER BY columns.
func (*SelectBuilder)Build¶
func (sb *SelectBuilder) Build() (sqlstring, args []interface{})
Build returns compiled SELECT string and args.They can be used in `DB#Query` of package `database/sql` directly.
func (*SelectBuilder)BuildWithFlavor¶
func (sb *SelectBuilder) BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})
BuildWithFlavor returns compiled SELECT string and args with flavor and initial args.They can be used in `DB#Query` of package `database/sql` directly.
func (*SelectBuilder)BuilderAs¶
func (sb *SelectBuilder) BuilderAs(builderBuilder, aliasstring)string
BuilderAs returns an AS expression wrapping a complex SQL.According to SQL syntax, SQL built by builder is surrounded by parens.
func (*SelectBuilder)Clone¶added inv1.37.0
func (sb *SelectBuilder) Clone() *SelectBuilder
Clone returns a deep copy of SelectBuilder.It's useful when you want to create a base builder and clone it to build similar queries.
func (*SelectBuilder)Descdeprecated
func (sb *SelectBuilder) Desc() *SelectBuilder
Desc sets order of ORDER BY to DESC.
Deprecated: Use OrderByDesc instead. Desc only supports a single direction for all ORDER BY columns.
func (*SelectBuilder)Distinct¶
func (sb *SelectBuilder) Distinct() *SelectBuilder
Distinct marks this SELECT as DISTINCT.
func (*SelectBuilder)Flavor¶added inv1.32.0
func (sb *SelectBuilder) Flavor()Flavor
Flavor returns flavor of builder
func (*SelectBuilder)ForShare¶added inv1.11.0
func (sb *SelectBuilder) ForShare() *SelectBuilder
ForShare adds FOR SHARE at the end of SELECT statement.
func (*SelectBuilder)ForUpdate¶added inv1.11.0
func (sb *SelectBuilder) ForUpdate() *SelectBuilder
ForUpdate adds FOR UPDATE at the end of SELECT statement.
Example¶
sb := newSelectBuilder()sb.Select("*").From("user").Where(sb.Equal("id", 1234),).ForUpdate()sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT * FROM user WHERE id = ? FOR UPDATE[1234]
func (*SelectBuilder)From¶
func (sb *SelectBuilder) From(table ...string) *SelectBuilder
From sets table names in SELECT.
func (*SelectBuilder)GroupBy¶
func (sb *SelectBuilder) GroupBy(col ...string) *SelectBuilder
GroupBy sets columns of GROUP BY in SELECT.
func (*SelectBuilder)Having¶
func (sb *SelectBuilder) Having(andExpr ...string) *SelectBuilder
Having sets expressions of HAVING in SELECT.
func (*SelectBuilder)Join¶added inv1.1.0
func (sb *SelectBuilder) Join(tablestring, onExpr ...string) *SelectBuilder
Join sets expressions of JOIN in SELECT.
It builds a JOIN expression like
JOIN table ON onExpr[0] AND onExpr[1] ...
func (*SelectBuilder)JoinWithOption¶added inv1.1.0
func (sb *SelectBuilder) JoinWithOption(optionJoinOption, tablestring, onExpr ...string) *SelectBuilder
JoinWithOption sets expressions of JOIN with an option.
It builds a JOIN expression like
option JOIN table ON onExpr[0] AND onExpr[1] ...
Here is a list of supported options.
- FullJoin: FULL JOIN
- FullOuterJoin: FULL OUTER JOIN
- InnerJoin: INNER JOIN
- LeftJoin: LEFT JOIN
- LeftOuterJoin: LEFT OUTER JOIN
- RightJoin: RIGHT JOIN
- RightOuterJoin: RIGHT OUTER JOIN
func (*SelectBuilder)LateralAs¶added inv1.33.0
func (sb *SelectBuilder) LateralAs(builderBuilder, aliasstring)string
LateralAs returns a LATERAL derived table expression wrapping a complex SQL.
Example¶
// Demo SQL comes from a sample on https://dev.mysql.com/doc/refman/8.4/en/lateral-derived-tables.html.sb := Select("salesperson.name","max_sale.amount","max_sale.customer_name",)sb.From("salesperson",sb.LateralAs(Select("amount", "customer_name").From("all_sales").Where("all_sales.salesperson_id = salesperson.id",).OrderByDesc("amount").Limit(1),"max_sale",),)fmt.Println(sb)Output:SELECT salesperson.name, max_sale.amount, max_sale.customer_name FROM salesperson, LATERAL (SELECT amount, customer_name FROM all_sales WHERE all_sales.salesperson_id = salesperson.id ORDER BY amount DESC LIMIT ?) AS max_sale
func (*SelectBuilder)Limit¶
func (sb *SelectBuilder) Limit(limitint) *SelectBuilder
Limit sets the LIMIT in SELECT.
func (*SelectBuilder)NumCol¶added inv1.25.0
func (sb *SelectBuilder) NumCol()int
NumCol returns the number of columns to select.
Example¶
sb := NewSelectBuilder()sb.Select("id", "name", "created_at")sb.From("demo.user")sb.Where(sb.GreaterThan("id", 1234),)// Count the number of columns.fmt.Println(sb.NumCol())Output:3
func (*SelectBuilder)Offset¶
func (sb *SelectBuilder) Offset(offsetint) *SelectBuilder
Offset sets the LIMIT offset in SELECT.
func (*SelectBuilder)OrderBydeprecated
func (sb *SelectBuilder) OrderBy(col ...string) *SelectBuilder
OrderBy sets columns of ORDER BY in SELECT.
Deprecated: Use OrderByAsc or OrderByDesc instead for better support of multiple ORDER BY columns with different directions.OrderBy combined with Asc/Desc only supports a single direction for all columns.
func (*SelectBuilder)OrderByAsc¶added inv1.38.0
func (sb *SelectBuilder) OrderByAsc(colstring) *SelectBuilder
OrderByAsc sets a column of ORDER BY in SELECT with ASC order.It supports chaining multiple calls to add multiple ORDER BY columns with different directions.
sb.OrderByAsc("name").OrderByDesc("id")// Generates: ORDER BY name ASC, id DESCExample¶
sb := NewSelectBuilder()sb.Select("id", "name", "score")sb.From("users")sb.Where(sb.GreaterThan("score", 0))sb.OrderByAsc("name")sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT id, name, score FROM users WHERE score > ? ORDER BY name ASC[0]
Example (Multiple)¶
sb := NewSelectBuilder()sb.Select("id", "name", "score")sb.From("users")sb.Where(sb.GreaterThan("score", 0))// Chain multiple OrderByAsc and OrderByDesc calls with different directionssb.OrderByDesc("score").OrderByAsc("name").OrderByDesc("id")sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT id, name, score FROM users WHERE score > ? ORDER BY score DESC, name ASC, id DESC[0]
func (*SelectBuilder)OrderByDesc¶added inv1.38.0
func (sb *SelectBuilder) OrderByDesc(colstring) *SelectBuilder
OrderByDesc sets a column of ORDER BY in SELECT with DESC order.It supports chaining multiple calls to add multiple ORDER BY columns with different directions.
sb.OrderByDesc("id").OrderByAsc("name")// Generates: ORDER BY id DESC, name ASCExample¶
sb := NewSelectBuilder()sb.Select("id", "name", "score")sb.From("users")sb.Where(sb.GreaterThan("score", 0))sb.OrderByDesc("score")sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT id, name, score FROM users WHERE score > ? ORDER BY score DESC[0]
func (*SelectBuilder)SQL¶added inv1.11.0
func (sb *SelectBuilder) SQL(sqlstring) *SelectBuilder
SQL adds an arbitrary sql to current position.
Example¶
sb := NewSelectBuilder()sb.SQL("/* before */")sb.Select("u.id", "u.name", "c.type", "p.nickname")sb.SQL("/* after select */")sb.From("user u")sb.SQL("/* after from */")sb.Join("contract c","u.id = c.user_id",)sb.JoinWithOption(RightOuterJoin, "person p","u.id = p.user_id",)sb.SQL("/* after join */")sb.Where("u.modified_at > u.created_at",)sb.SQL("/* after where */")sb.OrderBy("id")sb.SQL("/* after order by */")sb.Limit(10)sb.SQL("/* after limit */")sb.ForShare()sb.SQL("/* after for */")s := sb.String()fmt.Println(s)Output:/* before */ SELECT u.id, u.name, c.type, p.nickname /* after select */ FROM user u /* after from */ JOIN contract c ON u.id = c.user_id RIGHT OUTER JOIN person p ON u.id = p.user_id /* after join */ WHERE u.modified_at > u.created_at /* after where */ ORDER BY id /* after order by */ LIMIT ? /* after limit */ FOR SHARE /* after for */
func (*SelectBuilder)Select¶
func (sb *SelectBuilder) Select(col ...string) *SelectBuilder
Select sets columns in SELECT.
func (*SelectBuilder)SelectMore¶added inv1.29.0
func (sb *SelectBuilder) SelectMore(col ...string) *SelectBuilder
SelectMore adds more columns in SELECT.
func (*SelectBuilder)SetFlavor¶
func (sb *SelectBuilder) SetFlavor(flavorFlavor) (oldFlavor)
SetFlavor sets the flavor of compiled sql.
func (*SelectBuilder)String¶
func (sb *SelectBuilder) String()string
String returns the compiled SELECT string.
func (*SelectBuilder)TableNames¶added inv1.28.1
func (sb *SelectBuilder) TableNames() []string
TableNames returns all table names in this SELECT statement.
func (*SelectBuilder)Where¶
func (sb *SelectBuilder) Where(andExpr ...string) *SelectBuilder
Where sets expressions of WHERE in SELECT.
func (*SelectBuilder)With¶added inv1.28.0
func (sb *SelectBuilder) With(builder *CTEBuilder) *SelectBuilder
With sets WITH clause (the Common Table Expression) before SELECT.
Example¶
sql := With(CTEQuery("users").As(Select("id", "name").From("users").Where("prime IS NOT NULL"),),// The CTE table orders will be added to table list of FROM clause automatically.CTETable("orders").As(Select("id", "user_id").From("orders"),),).Select("orders.id").Join("users", "orders.user_id = users.id").Limit(10).String()fmt.Println(sql)Output:WITH users AS (SELECT id, name FROM users WHERE prime IS NOT NULL), orders AS (SELECT id, user_id FROM orders) SELECT orders.id FROM orders JOIN users ON orders.user_id = users.id LIMIT ?
typeStruct¶
type Struct struct {FlavorFlavor// contains filtered or unexported fields}Struct represents a struct type.
All methods in Struct are thread-safe.We can define a global variable to hold a Struct and use it in any goroutine.
Example (BuildDELETE)¶
// Suppose we defined following type for user db.type User struct {ID int64 `db:"id" fieldtag:"pk"`Name string `db:"name"`Status int `db:"status"`}// Parse user struct. The userStruct can be a global variable.// It's guraanteed to be thread-safe.var userStruct = NewStruct(new(User))// Prepare DELETE query.user := &User{ID: 1234,}b := userStruct.DeleteFrom("user")b.Where(b.Equal("id", user.ID))// Execute the query.sql, args := b.Build()orderDB.Exec(sql, args...)fmt.Println(sql)fmt.Println(args)Output:DELETE FROM user WHERE id = ?[1234]
Example (BuildINSERT)¶
// Suppose we defined following type for user db.type User struct {ID int64 `db:"id" fieldtag:"pk"`Name string `db:"name"`Status int `db:"status"`}// Parse user struct. The userStruct can be a global variable.// It's guraanteed to be thread-safe.var userStruct = NewStruct(new(User))// Prepare INSERT query.// Suppose that user id is generated by database.user := &User{Name: "Huan Du",Status: 1,}ib := userStruct.WithoutTag("pk").InsertInto("user", user)// Execute the query.sql, args := ib.Build()orderDB.Exec(sql, args...)fmt.Println(sql)fmt.Println(args)Output:INSERT INTO user (name, status) VALUES (?, ?)[Huan Du 1]
Example (BuildJOIN)¶
// Suppose we're going to query a "member" table joined with "user" table.type Member struct {ID string `db:"id"`UserID string `db:"user_id"`MemberName int `db:"name"`CreatedAt time.Time `db:"created_at"`// Add "u." prefix to the field name to specify the field in "user" table.Name string `db:"u.name"`Email string `db:"u.email"`}// Parse member struct. The memberStruct can be a global variable.// It's guraanteed to be thread-safe.var memberStruct = NewStruct(new(Member))// Prepare JOIN query.sb := memberStruct.SelectFrom("member m").Join("user u", "m.user_id = u.user_id")sb.Where(sb.Like("m.name", "Huan%"))sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT m.id, m.user_id, m.name, m.created_at, u.name, u.email FROM member m JOIN user u ON m.user_id = u.user_id WHERE m.name LIKE ?[Huan%]
Example (BuildUPDATE)¶
// Suppose we defined following type for user db.type User struct {ID int64 `db:"id" fieldtag:"pk"`Name string `db:"name"`Status int `db:"status"`}// Parse user struct. The userStruct can be a global variable.// It's guraanteed to be thread-safe.var userStruct = NewStruct(new(User))// Prepare UPDATE query.// We should not update the primary key field.user := &User{ID: 1234,Name: "Huan Du",Status: 1,}ub := userStruct.WithoutTag("pk").Update("user", user)ub.Where(ub.Equal("id", user.ID))// Execute the query.sql, args := ub.Build()orderDB.Exec(sql, args...)fmt.Println(sql)fmt.Println(args)Output:UPDATE user SET name = ?, status = ? WHERE id = ?[Huan Du 1 1234]
Example (ForCQL)¶
// Suppose we defined following type for user db.type User struct {ID int64 `db:"id" fieldtag:"pk"`Name string `db:"name"`Status int `db:"status"`}// Parse user struct. The userStruct can be a global variable.// It's guraanteed to be thread-safe.userStruct := NewStruct(new(User)).For(CQL)sb := userStruct.SelectFrom("user")sb.Where(sb.Equal("id", 1234))sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT id, name, status FROM user WHERE id = ?[1234]
Example (ForPostgreSQL)¶
// Suppose we defined following type for user db.type User struct {ID int64 `db:"id" fieldtag:"pk"`Name string `db:"name"`Status int `db:"status"`}// Parse user struct. The userStruct can be a global variable.// It's guraanteed to be thread-safe.var userStruct = NewStruct(new(User)).For(PostgreSQL)sb := userStruct.SelectFrom("user")sb.Where(sb.Equal("id", 1234))sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT user.id, user.name, user.status FROM user WHERE id = $1[1234]
Example (UseStructAsORM)¶
// Suppose we defined following type for user db.type User struct {ID int64 `db:"id" fieldtag:"pk"`Name string `db:"name"`Status int `db:"status"`}// Parse user struct. The userStruct can be a global variable.// It's guraanteed to be thread-safe.var userStruct = NewStruct(new(User))// Prepare SELECT query.sb := userStruct.SelectFrom("user")sb.Where(sb.Equal("id", 1234))// Execute the query.sql, args := sb.Build()rows, _ := userDB.Query(sql, args...)defer func(rows testRows) {_ = rows.Close()}(rows)// Scan row data to user.var user User_ = rows.Scan(userStruct.Addr(&user)...)fmt.Println(sql)fmt.Println(args)fmt.Printf("%#v", user)Output:SELECT user.id, user.name, user.status FROM user WHERE id = ?[1234]sqlbuilder.User{ID:1234, Name:"huandu", Status:1}
funcNewStruct¶
func NewStruct(structValue interface{}) *StructNewStruct analyzes type information in structValueand creates a new Struct with all structValue fields.If structValue is not a struct, NewStruct returns a dummy Struct.
func (*Struct)Addr¶
func (s *Struct) Addr(st interface{}) []interface{}
Addr takes address of all exported fields of the s from the st.The returned result can be used in `Row#Scan` directly.
func (*Struct)AddrForTagdeprecated
AddrForTag takes address of all fields of the s tagged with tag from the st.The returned value can be used in `Row#Scan` directly.
If tag is not defined in s in advance, returns nil.
Deprecated: It's recommended to use s.WithTag(tag).Addr(...) instead of calling this method.The former one is more readable and can be chained with other methods.
func (*Struct)AddrWithCols¶
AddrWithCols takes address of all columns defined in cols from the st.The returned value can be used in `Row#Scan` directly.
func (*Struct)Columns¶added inv1.14.0
Columns returns column names of s for all exported struct fields.
func (*Struct)ColumnsForTagdeprecatedadded inv1.14.0
func (*Struct)DeleteFrom¶
func (s *Struct) DeleteFrom(tablestring) *DeleteBuilder
DeleteFrom creates a new `DeleteBuilder` with table name.
Caller is responsible to set WHERE condition to match right record.
func (*Struct)For¶
For sets the default flavor of s and returns a shadow copy of s.The original s.Flavor is not changed.
func (*Struct)ForeachRead¶added inv1.23.0
func (s *Struct) ForeachRead(trans func(dbtagstring, isQuotedbool, fieldreflect.StructField))
ForeachRead foreach tags.
func (*Struct)ForeachWrite¶added inv1.23.0
func (s *Struct) ForeachWrite(trans func(dbtagstring, isQuotedbool, fieldreflect.StructField))
ForeachWrite foreach tags.
func (*Struct)InsertIgnoreInto¶added inv1.6.0
func (s *Struct) InsertIgnoreInto(tablestring, value ...interface{}) *InsertBuilder
InsertIgnoreInto creates a new `InsertBuilder` with table name using verb INSERT IGNORE INTO.By default, all exported fields of s are set as columns by calling `InsertBuilder#Cols`,and value is added as a list of values by calling `InsertBuilder#Values`.
InsertIgnoreInto never returns any error.If the type of any item in value is not expected, it will be ignored.If value is an empty slice, `InsertBuilder#Values` will not be called.
func (*Struct)InsertIgnoreIntoForTagdeprecatedadded inv1.6.0
func (s *Struct) InsertIgnoreIntoForTag(tablestring, tagstring, value ...interface{}) *InsertBuilder
InsertIgnoreIntoForTag creates a new `InsertBuilder` with table name using verb INSERT IGNORE INTO.By default, exported fields tagged with tag are set as columns by calling `InsertBuilder#Cols`,and value is added as a list of values by calling `InsertBuilder#Values`.
InsertIgnoreIntoForTag never returns any error.If the type of any item in value is not expected, it will be ignored.If value is an empty slice, `InsertBuilder#Values` will not be called.
Deprecated: It's recommended to use s.WithTag(tag).InsertIgnoreInto(...) instead of calling this method.The former one is more readable and can be chained with other methods.
func (*Struct)InsertInto¶
func (s *Struct) InsertInto(tablestring, value ...interface{}) *InsertBuilder
InsertInto creates a new `InsertBuilder` with table name using verb INSERT INTO.By default, all exported fields of s are set as columns by calling `InsertBuilder#Cols`,and value is added as a list of values by calling `InsertBuilder#Values`.
InsertInto never returns any error.If the type of any item in value is not expected, it will be ignored.If value is an empty slice, `InsertBuilder#Values` will not be called.
func (*Struct)InsertIntoForTagdeprecated
func (s *Struct) InsertIntoForTag(tablestring, tagstring, value ...interface{}) *InsertBuilder
InsertIntoForTag creates a new `InsertBuilder` with table name using verb INSERT INTO.By default, exported fields tagged with tag are set as columns by calling `InsertBuilder#Cols`,and value is added as a list of values by calling `InsertBuilder#Values`.
InsertIntoForTag never returns any error.If the type of any item in value is not expected, it will be ignored.If value is an empty slice, `InsertBuilder#Values` will not be called.
Deprecated: It's recommended to use s.WithTag(tag).InsertInto(...) instead of calling this method.The former one is more readable and can be chained with other methods.
func (*Struct)ReplaceInto¶added inv1.6.0
func (s *Struct) ReplaceInto(tablestring, value ...interface{}) *InsertBuilder
ReplaceInto creates a new `InsertBuilder` with table name using verb REPLACE INTO.By default, all exported fields of s are set as columns by calling `InsertBuilder#Cols`,and value is added as a list of values by calling `InsertBuilder#Values`.
ReplaceInto never returns any error.If the type of any item in value is not expected, it will be ignored.If value is an empty slice, `InsertBuilder#Values` will not be called.
func (*Struct)ReplaceIntoForTagdeprecatedadded inv1.6.0
func (s *Struct) ReplaceIntoForTag(tablestring, tagstring, value ...interface{}) *InsertBuilder
ReplaceIntoForTag creates a new `InsertBuilder` with table name using verb REPLACE INTO.By default, exported fields tagged with tag are set as columns by calling `InsertBuilder#Cols`,and value is added as a list of values by calling `InsertBuilder#Values`.
ReplaceIntoForTag never returns any error.If the type of any item in value is not expected, it will be ignored.If value is an empty slice, `InsertBuilder#Values` will not be called.
Deprecated: It's recommended to use s.WithTag(tag).ReplaceInto(...) instead of calling this method.The former one is more readable and can be chained with other methods.
func (*Struct)SelectFrom¶
func (s *Struct) SelectFrom(tablestring) *SelectBuilder
SelectFrom creates a new `SelectBuilder` with table name.By default, all exported fields of the s are listed as columns in SELECT.
Caller is responsible to set WHERE condition to find right record.
func (*Struct)SelectFromForTagdeprecated
func (s *Struct) SelectFromForTag(tablestring, tagstring) (sb *SelectBuilder)
SelectFromForTag creates a new `SelectBuilder` with table name for a specified tag.By default, all fields of the s tagged with tag are listed as columns in SELECT.
Caller is responsible to set WHERE condition to find right record.
Deprecated: It's recommended to use s.WithTag(tag).SelectFrom(...) instead of calling this method.The former one is more readable and can be chained with other methods.
func (*Struct)Update¶
func (s *Struct) Update(tablestring, value interface{}) *UpdateBuilder
Update creates a new `UpdateBuilder` with table name.By default, all exported fields of the s is assigned in UPDATE with the field values from value.If value's type is not the same as that of s, Update returns a dummy `UpdateBuilder` with table name.
Caller is responsible to set WHERE condition to match right record.
func (*Struct)UpdateForTagdeprecated
func (s *Struct) UpdateForTag(tablestring, tagstring, value interface{}) *UpdateBuilder
UpdateForTag creates a new `UpdateBuilder` with table name.By default, all fields of the s tagged with tag is assigned in UPDATE with the field values from value.If value's type is not the same as that of s, UpdateForTag returns a dummy `UpdateBuilder` with table name.
Caller is responsible to set WHERE condition to match right record.
Deprecated: It's recommended to use s.WithTag(tag).Update(...) instead of calling this method.The former one is more readable and can be chained with other methods.
func (*Struct)Values¶added inv1.14.0
func (s *Struct) Values(st interface{}) []interface{}
Values returns a shadow copy of all exported fields in st.
func (*Struct)ValuesForTagdeprecatedadded inv1.14.0
ValuesForTag returns a shadow copy of all fields tagged with tag in st.
Deprecated: It's recommended to use s.WithTag(tag).Values(...) instead of calling this method.The former one is more readable and can be chained with other methods.
func (*Struct)WithFieldMapper¶added inv1.12.0
func (s *Struct) WithFieldMapper(mapperFieldMapperFunc) *Struct
WithFieldMapper returns a new Struct based on s with custom field mapper.The original s is not changed.
func (*Struct)WithTag¶added inv1.15.1
WithTag sets included tag(s) for all builder methods.For instance, calling s.WithTag("tag").SelectFrom("t") is to select all fields tagged with "tag" from table "t".
If multiple tags are provided, fields tagged with any of them are included.That is, s.WithTag("tag1", "tag2").SelectFrom("t") is to select all fields tagged with "tag1" or "tag2" from table "t".
Example¶
// Suppose we defined following type for an order.type Order struct {ID int64 `db:"id"`State State `db:"state" fieldtag:"paid"`SkuID int64 `db:"sku_id"`UserID int64 `db:"user_id"`Price int64 `db:"price" fieldtag:"update"`Discount int64 `db:"discount" fieldtag:"update"`Desc string `db:"desc" fieldtag:"new,update" fieldopt:"withquote"`CreatedAt int64 `db:"created_at"`ModifiedAt int64 `db:"modified_at" fieldtag:"update,paid"`}// The orderStruct is a global variable for Order type.var orderStruct = NewStruct(new(Order))// Create an order with all fields set.createOrder := func(table string) {now := time.Now().Unix()order := &Order{ID: 1234,State: OrderStateCreated,SkuID: 5678,UserID: 7527,Price: 1000,Discount: 0,Desc: "Best goods",CreatedAt: now,ModifiedAt: now,}b := orderStruct.InsertInto(table, &order)sql, args := b.Build()orderDB.Exec(sql, args)fmt.Println(sql)}// Update order only with price related fields, which is tagged with "update".updatePrice := func(table string) {// Use tag "update" in all struct methods.st := orderStruct.WithTag("update")// Read order from database.var order Ordersql, args := st.SelectFrom(table).Where("id = 1234").Build()rows, _ := orderDB.Query(sql, args...)defer func(rows testRows) {_ = rows.Close()}(rows)_ = rows.Scan(st.Addr(&order)...)fmt.Println(sql)// Discount for this user.// Use tag "update" to update necessary columns only.order.Discount += 100order.ModifiedAt = time.Now().Unix()// Save the order.b := st.Update(table, &order)b.Where(b.E("id", order.ID))sql, args = b.Build()orderDB.Exec(sql, args...)fmt.Println(sql)}// Update order only with payment related fields, which is tagged with "paid".updateState := func(table string) {st := orderStruct.WithTag("paid")// Read order from database.var order Ordersql, args := st.SelectFrom(table).Where("id = 1234").Build()rows, _ := orderDB.Query(sql, args...)defer func(rows testRows) {_ = rows.Close()}(rows)_ = rows.Scan(st.Addr(&order)...)fmt.Println(sql)// Update state to paid when user has paid for the order.// Use tag "paid" to update necessary columns only.if order.State != OrderStateCreated {// Report state error here.panic(order.State)// return}// Update order state.order.State = OrderStatePaidorder.ModifiedAt = time.Now().Unix()// Save the order.b := st.Update(table, &order)b.Where(b.E("id", order.ID))sql, args = b.Build()orderDB.Exec(sql, args...)fmt.Println(sql)}table := "order"createOrder(table)updatePrice(table)updateState(table)Output:INSERT INTO order (id, state, sku_id, user_id, price, discount, `desc`, created_at, modified_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)SELECT order.price, order.discount, order.`desc`, order.modified_at FROM order WHERE id = 1234UPDATE order SET price = ?, discount = ?, `desc` = ?, modified_at = ? WHERE id = ?SELECT order.state, order.modified_at FROM order WHERE id = 1234UPDATE order SET state = ?, modified_at = ? WHERE id = ?
func (*Struct)WithoutTag¶added inv1.20.0
WithoutTag sets excluded tag(s) for all builder methods.For instance, calling s.WithoutTag("tag").SelectFrom("t") is to select all fields except those tagged with "tag" from table "t".
If multiple tags are provided, fields tagged with any of them are excluded.That is, s.WithoutTag("tag1", "tag2").SelectFrom("t") is to exclude any field tagged with "tag1" or "tag2" from table "t".
Example¶
// We can use WithoutTag to exclude fields with specific tag.// It's useful when we want to update all fields except some fields.type User struct {ID int64 `db:"id" fieldtag:"pk"`FirstName string `db:"first_name"`LastName string `db:"last_name"`ModifiedAtTime time.Time `db:"modified_at_time"`}// The userStruct is a global variable for User type.var userStruct = NewStruct(new(User))// Update user with all fields except the user_id field which is tagged with "pk".user := &User{FirstName: "Huan",LastName: "Du",ModifiedAtTime: time.Now(),}sql, _ := userStruct.WithoutTag("pk").Update("user", user).Where("id = 1234").Build()fmt.Println(sql)Output:UPDATE user SET first_name = ?, last_name = ?, modified_at_time = ? WHERE id = 1234
typeUnionBuilder¶added inv1.8.0
type UnionBuilder struct {// contains filtered or unexported fields}UnionBuilder is a builder to build UNION.
Example (Limit_offset)¶
flavors := []Flavor{MySQL, PostgreSQL, SQLite, SQLServer, CQL, ClickHouse, Presto, Oracle, Informix, Doris}results := make([][]string, len(flavors))ub := NewUnionBuilder()saveResults := func() {sb1 := NewSelectBuilder()sb1.Select("*").From("user1")sb2 := NewSelectBuilder()sb2.Select("*").From("user2")ub.Union(sb1, sb2)for i, f := range flavors {s, _ := ub.BuildWithFlavor(f)results[i] = append(results[i], s)}}// Case #1: limit < 0 and offset < 0//// All: No limit or offset in query.ub.Limit(-1)ub.Offset(-1)saveResults()// Case #2: limit < 0 and offset >= 0//// MySQL and SQLite: Ignore offset if the limit is not set.// PostgreSQL: Offset can be set without limit.// SQLServer: Offset can be set without limit.// CQL: Ignore offset.// Oracle: Offset can be set without limit.ub.Limit(-1)ub.Offset(0)saveResults()// Case #3: limit >= 0 and offset >= 0//// CQL: Ignore offset.// All others: Set both limit and offset.ub.Limit(1)ub.Offset(0)saveResults()// Case #4: limit >= 0 and offset < 0//// All: Set limit in query.ub.Limit(1)ub.Offset(-1)saveResults()// Case #5: limit >= 0 and offset >= 0 order by id//// CQL: Ignore offset.// All others: Set both limit and offset.ub.Limit(1)ub.Offset(1)ub.OrderBy("id")saveResults()for i, result := range results {fmt.Println()fmt.Println(flavors[i])for n, s := range result {fmt.Printf("#%d: %s\n", n+1, s)}}Output:MySQL#1: (SELECT * FROM user1) UNION (SELECT * FROM user2)#2: (SELECT * FROM user1) UNION (SELECT * FROM user2)#3: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT ? OFFSET ?#4: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT ?#5: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY id LIMIT ? OFFSET ?PostgreSQL#1: (SELECT * FROM user1) UNION (SELECT * FROM user2)#2: (SELECT * FROM user1) UNION (SELECT * FROM user2) OFFSET $1#3: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT $1 OFFSET $2#4: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT $1#5: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY id LIMIT $1 OFFSET $2SQLite#1: SELECT * FROM user1 UNION SELECT * FROM user2#2: SELECT * FROM user1 UNION SELECT * FROM user2#3: SELECT * FROM user1 UNION SELECT * FROM user2 LIMIT ? OFFSET ?#4: SELECT * FROM user1 UNION SELECT * FROM user2 LIMIT ?#5: SELECT * FROM user1 UNION SELECT * FROM user2 ORDER BY id LIMIT ? OFFSET ?SQLServer#1: (SELECT * FROM user1) UNION (SELECT * FROM user2)#2: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY 1 OFFSET @p1 ROWS#3: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY 1 OFFSET @p1 ROWS FETCH NEXT @p2 ROWS ONLY#4: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY 1 OFFSET 0 ROWS FETCH NEXT @p1 ROWS ONLY#5: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY id OFFSET @p1 ROWS FETCH NEXT @p2 ROWS ONLYCQL#1: (SELECT * FROM user1) UNION (SELECT * FROM user2)#2: (SELECT * FROM user1) UNION (SELECT * FROM user2)#3: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT ?#4: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT ?#5: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY id LIMIT ?ClickHouse#1: (SELECT * FROM user1) UNION (SELECT * FROM user2)#2: (SELECT * FROM user1) UNION (SELECT * FROM user2)#3: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT ? OFFSET ?#4: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT ?#5: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY id LIMIT ? OFFSET ?Presto#1: (SELECT * FROM user1) UNION (SELECT * FROM user2)#2: (SELECT * FROM user1) UNION (SELECT * FROM user2) OFFSET ?#3: (SELECT * FROM user1) UNION (SELECT * FROM user2) OFFSET ? LIMIT ?#4: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT ?#5: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY id OFFSET ? LIMIT ?Oracle#1: (SELECT * FROM user1) UNION (SELECT * FROM user2)#2: SELECT * FROM ( (SELECT * FROM user1) UNION (SELECT * FROM user2) ) OFFSET :1 ROWS#3: SELECT * FROM ( (SELECT * FROM user1) UNION (SELECT * FROM user2) ) OFFSET :1 ROWS FETCH NEXT :2 ROWS ONLY#4: SELECT * FROM ( (SELECT * FROM user1) UNION (SELECT * FROM user2) ) OFFSET 0 ROWS FETCH NEXT :1 ROWS ONLY#5: SELECT * FROM ( (SELECT * FROM user1) UNION (SELECT * FROM user2) ) ORDER BY id OFFSET :1 ROWS FETCH NEXT :2 ROWS ONLYInformix#1: (SELECT * FROM user1) UNION (SELECT * FROM user2)#2: (SELECT * FROM user1) UNION (SELECT * FROM user2)#3: SELECT * FROM ( (SELECT * FROM user1) UNION (SELECT * FROM user2) ) SKIP ? FIRST ?#4: SELECT * FROM ( (SELECT * FROM user1) UNION (SELECT * FROM user2) ) FIRST ?#5: SELECT * FROM ( (SELECT * FROM user1) UNION (SELECT * FROM user2) ) ORDER BY id SKIP ? FIRST ?Doris#1: (SELECT * FROM user1) UNION (SELECT * FROM user2)#2: (SELECT * FROM user1) UNION (SELECT * FROM user2)#3: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT 1 OFFSET 0#4: (SELECT * FROM user1) UNION (SELECT * FROM user2) LIMIT 1#5: (SELECT * FROM user1) UNION (SELECT * FROM user2) ORDER BY id LIMIT 1 OFFSET 1
funcNewUnionBuilder¶added inv1.11.0
func NewUnionBuilder() *UnionBuilder
NewUnionBuilder creates a new UNION builder.
funcUnion¶added inv1.8.0
func Union(builders ...Builder) *UnionBuilder
Union unions all builders together using UNION operator.
Example¶
sb1 := NewSelectBuilder()sb1.Select("id", "name", "created_at")sb1.From("demo.user")sb1.Where(sb1.GreaterThan("id", 1234),)sb2 := newSelectBuilder()sb2.Select("id", "avatar")sb2.From("demo.user_profile")sb2.Where(sb2.In("status", 1, 2, 5),)ub := Union(sb1, sb2)ub.OrderByDesc("created_at")sql, args := ub.Build()fmt.Println(sql)fmt.Println(args)Output:(SELECT id, name, created_at FROM demo.user WHERE id > ?) UNION (SELECT id, avatar FROM demo.user_profile WHERE status IN (?, ?, ?)) ORDER BY created_at DESC[1234 1 2 5]
funcUnionAll¶added inv1.8.0
func UnionAll(builders ...Builder) *UnionBuilder
UnionAll unions all builders together using UNION ALL operator.
Example¶
sb := NewSelectBuilder()sb.Select("id", "name", "created_at")sb.From("demo.user")sb.Where(sb.GreaterThan("id", 1234),)ub := UnionAll(sb, Build("TABLE demo.user_profile"))ub.OrderByAsc("created_at")ub.Limit(100).Offset(5)sql, args := ub.Build()fmt.Println(sql)fmt.Println(args)Output:(SELECT id, name, created_at FROM demo.user WHERE id > ?) UNION ALL (TABLE demo.user_profile) ORDER BY created_at ASC LIMIT ? OFFSET ?[1234 100 5]
func (*UnionBuilder)Ascdeprecatedadded inv1.8.0
func (ub *UnionBuilder) Asc() *UnionBuilder
Asc sets order of ORDER BY to ASC.
Deprecated: Use OrderByAsc instead. Asc only supports a single direction for all ORDER BY columns.
func (*UnionBuilder)Build¶added inv1.8.0
func (ub *UnionBuilder) Build() (sqlstring, args []interface{})
Build returns compiled SELECT string and args.They can be used in `DB#Query` of package `database/sql` directly.
func (*UnionBuilder)BuildWithFlavor¶added inv1.8.0
func (ub *UnionBuilder) BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})
BuildWithFlavor returns compiled SELECT string and args with flavor and initial args.They can be used in `DB#Query` of package `database/sql` directly.
func (*UnionBuilder)Clone¶added inv1.37.0
func (ub *UnionBuilder) Clone() *UnionBuilder
Clone returns a deep copy of UnionBuilder.It's useful when you want to create a base builder and clone it to build similar queries.
func (*UnionBuilder)Descdeprecatedadded inv1.8.0
func (ub *UnionBuilder) Desc() *UnionBuilder
Desc sets order of ORDER BY to DESC.
Deprecated: Use OrderByDesc instead. Desc only supports a single direction for all ORDER BY columns.
func (*UnionBuilder)Flavor¶added inv1.32.0
func (ub *UnionBuilder) Flavor()Flavor
Flavor returns flavor of builder
func (*UnionBuilder)Limit¶added inv1.8.0
func (ub *UnionBuilder) Limit(limitint) *UnionBuilder
Limit sets the LIMIT in SELECT.
func (*UnionBuilder)Offset¶added inv1.8.0
func (ub *UnionBuilder) Offset(offsetint) *UnionBuilder
Offset sets the LIMIT offset in SELECT.
func (*UnionBuilder)OrderBydeprecatedadded inv1.8.0
func (ub *UnionBuilder) OrderBy(col ...string) *UnionBuilder
OrderBy sets columns of ORDER BY in SELECT.
Deprecated: Use OrderByAsc or OrderByDesc instead for better support of multiple ORDER BY columns with different directions.OrderBy combined with Asc/Desc only supports a single direction for all columns.
func (*UnionBuilder)OrderByAsc¶added inv1.38.0
func (ub *UnionBuilder) OrderByAsc(colstring) *UnionBuilder
OrderByAsc sets a column of ORDER BY in SELECT with ASC order.It supports chaining multiple calls to add multiple ORDER BY columns with different directions.
ub.OrderByAsc("name").OrderByDesc("id")// Generates: ORDER BY name ASC, id DESCfunc (*UnionBuilder)OrderByDesc¶added inv1.38.0
func (ub *UnionBuilder) OrderByDesc(colstring) *UnionBuilder
OrderByDesc sets a column of ORDER BY in SELECT with DESC order.It supports chaining multiple calls to add multiple ORDER BY columns with different directions.
ub.OrderByDesc("id").OrderByAsc("name")// Generates: ORDER BY id DESC, name ASCfunc (*UnionBuilder)SQL¶added inv1.11.0
func (ub *UnionBuilder) SQL(sqlstring) *UnionBuilder
SQL adds an arbitrary sql to current position.
Example¶
sb1 := NewSelectBuilder()sb1.Select("id", "name", "created_at")sb1.From("demo.user")sb2 := newSelectBuilder()sb2.Select("id", "avatar")sb2.From("demo.user_profile")ub := NewUnionBuilder()ub.SQL("/* before */")ub.Union(sb1, sb2)ub.SQL("/* after union */")ub.OrderBy("created_at").Desc()ub.SQL("/* after order by */")ub.Limit(100).Offset(5)ub.SQL("/* after limit */")sql := ub.String()fmt.Println(sql)Output:/* before */ (SELECT id, name, created_at FROM demo.user) UNION (SELECT id, avatar FROM demo.user_profile) /* after union */ ORDER BY created_at DESC /* after order by */ LIMIT ? OFFSET ? /* after limit */
func (*UnionBuilder)SetFlavor¶added inv1.8.0
func (ub *UnionBuilder) SetFlavor(flavorFlavor) (oldFlavor)
SetFlavor sets the flavor of compiled sql.
func (*UnionBuilder)String¶added inv1.8.0
func (ub *UnionBuilder) String()string
String returns the compiled SELECT string.
func (*UnionBuilder)Union¶added inv1.11.0
func (ub *UnionBuilder) Union(builders ...Builder) *UnionBuilder
Union unions all builders together using UNION operator.
func (*UnionBuilder)UnionAll¶added inv1.11.0
func (ub *UnionBuilder) UnionAll(builders ...Builder) *UnionBuilder
UnionAll unions all builders together using UNION ALL operator.
func (*UnionBuilder)Var¶added inv1.11.0
func (ub *UnionBuilder) Var(arg interface{})string
Var returns a placeholder for value.
typeUpdateBuilder¶
type UpdateBuilder struct {*WhereClauseCond// contains filtered or unexported fields}UpdateBuilder is a builder to build UPDATE.
Example¶
ub := NewUpdateBuilder()ub.Update("demo.user")ub.Set(ub.Assign("type", "sys"),ub.Incr("credit"),"modified_at = UNIX_TIMESTAMP(NOW())", // It's allowed to write arbitrary SQL.)ub.Where(ub.GreaterThan("id", 1234),ub.Like("name", "%Du"),ub.Or(ub.IsNull("id_card"),ub.In("status", 1, 2, 5),),"modified_at > created_at + "+ub.Var(86400), // It's allowed to write arbitrary SQL.)ub.OrderByAsc("id")sql, args := ub.Build()fmt.Println(sql)fmt.Println(args)Output:UPDATE demo.user SET type = ?, credit = credit + 1, modified_at = UNIX_TIMESTAMP(NOW()) WHERE id > ? AND name LIKE ? AND (id_card IS NULL OR status IN (?, ?, ?)) AND modified_at > created_at + ? ORDER BY id ASC[sys 1234 %Du 1 2 5 86400]
funcNewUpdateBuilder¶
func NewUpdateBuilder() *UpdateBuilder
NewUpdateBuilder creates a new UPDATE builder.
funcUpdate¶added inv1.11.0
func Update(table ...string) *UpdateBuilder
Update sets table name in UPDATE.
Example¶
sql := Update("demo.user").Set("visited = visited + 1",).Where("id = 1234",).String()fmt.Println(sql)Output:UPDATE demo.user SET visited = visited + 1 WHERE id = 1234
func (*UpdateBuilder)Add¶
func (ub *UpdateBuilder) Add(fieldstring, value interface{})string
Add represents SET "field = field + value" in UPDATE.
func (*UpdateBuilder)AddWhereClause¶added inv1.27.0
func (ub *UpdateBuilder) AddWhereClause(whereClause *WhereClause) *UpdateBuilder
AddWhereClause adds all clauses in the whereClause to SELECT.
func (*UpdateBuilder)Ascdeprecatedadded inv1.11.0
func (ub *UpdateBuilder) Asc() *UpdateBuilder
Asc sets order of ORDER BY to ASC.
Deprecated: Use OrderByAsc instead. Asc only supports a single direction for all ORDER BY columns.
func (*UpdateBuilder)Assign¶
func (ub *UpdateBuilder) Assign(fieldstring, value interface{})string
Assign represents SET "field = value" in UPDATE.
func (*UpdateBuilder)Build¶
func (ub *UpdateBuilder) Build() (sqlstring, args []interface{})
Build returns compiled UPDATE string and args.They can be used in `DB#Query` of package `database/sql` directly.
func (*UpdateBuilder)BuildWithFlavor¶
func (ub *UpdateBuilder) BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})
BuildWithFlavor returns compiled UPDATE string and args with flavor and initial args.They can be used in `DB#Query` of package `database/sql` directly.
func (*UpdateBuilder)Clone¶added inv1.37.0
func (ub *UpdateBuilder) Clone() *UpdateBuilder
Clone returns a deep copy of UpdateBuilder.It's useful when you want to create a base builder and clone it to build similar queries.
func (*UpdateBuilder)Decr¶
func (ub *UpdateBuilder) Decr(fieldstring)string
Decr represents SET "field = field - 1" in UPDATE.
func (*UpdateBuilder)Descdeprecatedadded inv1.11.0
func (ub *UpdateBuilder) Desc() *UpdateBuilder
Desc sets order of ORDER BY to DESC.
Deprecated: Use OrderByDesc instead. Desc only supports a single direction for all ORDER BY columns.
func (*UpdateBuilder)Div¶
func (ub *UpdateBuilder) Div(fieldstring, value interface{})string
Div represents SET "field = field / value" in UPDATE.
func (*UpdateBuilder)Flavor¶added inv1.32.0
func (ub *UpdateBuilder) Flavor()Flavor
Flavor returns flavor of builder
func (*UpdateBuilder)Incr¶
func (ub *UpdateBuilder) Incr(fieldstring)string
Incr represents SET "field = field + 1" in UPDATE.
func (*UpdateBuilder)Limit¶added inv1.11.0
func (ub *UpdateBuilder) Limit(limitint) *UpdateBuilder
Limit sets the LIMIT in UPDATE.
func (*UpdateBuilder)Mul¶
func (ub *UpdateBuilder) Mul(fieldstring, value interface{})string
Mul represents SET "field = field * value" in UPDATE.
func (*UpdateBuilder)NumAssignment¶added inv1.25.0
func (ub *UpdateBuilder) NumAssignment()int
NumAssignment returns the number of assignments to update.
Example¶
ub := NewUpdateBuilder()ub.Update("demo.user")ub.Set(ub.Assign("type", "sys"),ub.Incr("credit"),"modified_at = UNIX_TIMESTAMP(NOW())",)// Count the number of assignments.fmt.Println(ub.NumAssignment())Output:3
func (*UpdateBuilder)OrderBydeprecatedadded inv1.11.0
func (ub *UpdateBuilder) OrderBy(col ...string) *UpdateBuilder
OrderBy sets columns of ORDER BY in UPDATE.
Deprecated: Use OrderByAsc or OrderByDesc instead for better support of multiple ORDER BY columns with different directions.OrderBy combined with Asc/Desc only supports a single direction for all columns.
func (*UpdateBuilder)OrderByAsc¶added inv1.38.0
func (ub *UpdateBuilder) OrderByAsc(colstring) *UpdateBuilder
OrderByAsc sets a column of ORDER BY in UPDATE with ASC order.It supports chaining multiple calls to add multiple ORDER BY columns with different directions.
ub.OrderByAsc("name").OrderByDesc("id")// Generates: ORDER BY name ASC, id DESCfunc (*UpdateBuilder)OrderByDesc¶added inv1.38.0
func (ub *UpdateBuilder) OrderByDesc(colstring) *UpdateBuilder
OrderByDesc sets a column of ORDER BY in UPDATE with DESC order.It supports chaining multiple calls to add multiple ORDER BY columns with different directions.
ub.OrderByDesc("id").OrderByAsc("name")// Generates: ORDER BY id DESC, name ASCfunc (*UpdateBuilder)Returning¶added inv1.36.0
func (ub *UpdateBuilder) Returning(col ...string) *UpdateBuilder
Returning sets returning columns.For DBMS that doesn't support RETURNING, e.g. MySQL, it will be ignored.
Example¶
ub := NewUpdateBuilder()ub.Update("user")ub.Set(ub.Assign("name", "Huan Du"))ub.Where(ub.Equal("id", 123))ub.Returning("id", "updated_at")sql, args := ub.BuildWithFlavor(PostgreSQL)fmt.Println(sql)fmt.Println(args)Output:UPDATE user SET name = $1 WHERE id = $2 RETURNING id, updated_at[Huan Du 123]
func (*UpdateBuilder)SQL¶added inv1.11.0
func (ub *UpdateBuilder) SQL(sqlstring) *UpdateBuilder
SQL adds an arbitrary sql to current position.
Example¶
ub := NewUpdateBuilder()ub.SQL("/* before */")ub.Update("demo.user")ub.SQL("/* after update */")ub.Set(ub.Assign("type", "sys"),)ub.SQL("/* after set */")ub.OrderByDesc("id")ub.SQL("/* after order by */")ub.Limit(10)ub.SQL("/* after limit */")sql := ub.String()fmt.Println(sql)Output:/* before */ UPDATE demo.user /* after update */ SET type = ? /* after set */ ORDER BY id DESC /* after order by */ LIMIT ? /* after limit */
func (*UpdateBuilder)Set¶
func (ub *UpdateBuilder) Set(assignment ...string) *UpdateBuilder
Set sets the assignments in SET.
func (*UpdateBuilder)SetFlavor¶
func (ub *UpdateBuilder) SetFlavor(flavorFlavor) (oldFlavor)
SetFlavor sets the flavor of compiled sql.
func (*UpdateBuilder)SetMore¶added inv1.4.2
func (ub *UpdateBuilder) SetMore(assignment ...string) *UpdateBuilder
SetMore appends the assignments in SET.
Example¶
ub := NewUpdateBuilder()ub.Update("demo.user")ub.Set(ub.Assign("type", "sys"),ub.Incr("credit"),)ub.SetMore("modified_at = UNIX_TIMESTAMP(NOW())", // It's allowed to write arbitrary SQL.)sql, args := ub.Build()fmt.Println(sql)fmt.Println(args)Output:UPDATE demo.user SET type = ?, credit = credit + 1, modified_at = UNIX_TIMESTAMP(NOW())[sys]
func (*UpdateBuilder)String¶
func (ub *UpdateBuilder) String()string
String returns the compiled UPDATE string.
func (*UpdateBuilder)Sub¶
func (ub *UpdateBuilder) Sub(fieldstring, value interface{})string
Sub represents SET "field = field - value" in UPDATE.
func (*UpdateBuilder)TableNames¶added inv1.32.0
func (ub *UpdateBuilder) TableNames() (tableNames []string)
TableNames returns all table names in this UPDATE statement.
func (*UpdateBuilder)Update¶
func (ub *UpdateBuilder) Update(table ...string) *UpdateBuilder
Update sets table name in UPDATE.
func (*UpdateBuilder)Where¶
func (ub *UpdateBuilder) Where(andExpr ...string) *UpdateBuilder
Where sets expressions of WHERE in UPDATE.
func (*UpdateBuilder)With¶added inv1.29.0
func (ub *UpdateBuilder) With(builder *CTEBuilder) *UpdateBuilder
With sets WITH clause (the Common Table Expression) before UPDATE.
Example¶
sql := With(CTETable("users").As(Select("id", "name").From("users").Where("prime IS NOT NULL"),),).Update("orders").Set("orders.transport_fee = 0",).Where("users.id = orders.user_id",).String()fmt.Println(sql)Output:WITH users AS (SELECT id, name FROM users WHERE prime IS NOT NULL) UPDATE orders, users SET orders.transport_fee = 0 WHERE users.id = orders.user_id
typeWhereClause¶added inv1.27.0
type WhereClause struct {// contains filtered or unexported fields}WhereClause is a Builder for WHERE clause.All builders which support `WHERE` clause have an anonymous `WhereClause` field,in which the conditions are stored.
WhereClause can be shared among multiple builders.However, it is not thread-safe.
Example¶
// Build a SQL to select a user from database.sb := Select("name", "level").From("users")sb.Where(sb.Equal("id", 1234),)sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)// Query database with the sql and update this user's level...ub := Update("users")ub.Set(ub.Add("level", 10),)// The WHERE clause of UPDATE should be the same as the WHERE clause of SELECT.ub.WhereClause = sb.WhereClausesql, args = ub.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT name, level FROM users WHERE id = ?[1234]UPDATE users SET level = level + ? WHERE id = ?[10 1234]
Example (ClearWhereClause)¶
db := DeleteFrom("users")db.Where(db.GreaterThan("level", 10),)sql, args := db.Build()fmt.Println(sql)fmt.Println(args)// Clear WHERE clause.db.WhereClause = nilsql, args = db.Build()fmt.Println(sql)fmt.Println(args)db.Where(db.Equal("id", 1234),)sql, args = db.Build()fmt.Println(sql)fmt.Println(args)Output:DELETE FROM users WHERE level > ?[10]DELETE FROM users[]DELETE FROM users WHERE id = ?[1234]
Example (SharedAmongBuilders)¶
// A WhereClause can be shared among builders.// However, as it's not thread-safe, don't use it in a concurrent environment.sb1 := Select("level").From("users")sb2 := Select("status").From("users")// Share the same WhereClause between sb1 and sb2.whereClause := NewWhereClause()sb1.WhereClause = whereClausesb2.WhereClause = whereClause// The Where method in sb1 and sb2 will update the same WhereClause.// When we call sb1.Where(), the WHERE clause in sb2 will also be updated.sb1.Where(sb1.Like("name", "Charmy%"),)// We can get a copy of the WhereClause.// The copy is independent from the original.sb3 := Select("name").From("users")sb3.WhereClause = CopyWhereClause(whereClause)// Adding more expressions to sb1 and sb2 will not affect sb3.sb2.Where(sb2.In("status", 1, 2, 3),)// Adding more expressions to sb3 will not affect sb1 and sb2.sb3.Where(sb3.GreaterEqualThan("level", 10),)sql1, args1 := sb1.Build()sql2, args2 := sb2.Build()sql3, args3 := sb3.Build()fmt.Println(sql1)fmt.Println(args1)fmt.Println(sql2)fmt.Println(args2)fmt.Println(sql3)fmt.Println(args3)Output:SELECT level FROM users WHERE name LIKE ? AND status IN (?, ?, ?)[Charmy% 1 2 3]SELECT status FROM users WHERE name LIKE ? AND status IN (?, ?, ?)[Charmy% 1 2 3]SELECT name FROM users WHERE name LIKE ? AND level >= ?[Charmy% 10]
funcCopyWhereClause¶added inv1.27.0
func CopyWhereClause(whereClause *WhereClause) *WhereClause
CopyWhereClause creates a copy of the whereClause.
funcNewWhereClause¶added inv1.27.0
func NewWhereClause() *WhereClause
NewWhereClause creates a new WhereClause.
func (*WhereClause)AddWhereClause¶added inv1.27.0
func (wc *WhereClause) AddWhereClause(whereClause *WhereClause) *WhereClause
AddWhereClause adds all clauses in the whereClause to the wc.
Example¶
sb := Select("level").From("users")sb.Where(sb.Equal("id", 1234),)sql, args := sb.Build()fmt.Println(sql)fmt.Println(args)ub := Update("users")ub.Set(ub.Add("level", 10),)// Copy the WHERE clause of sb into ub and add more expressions.ub.AddWhereClause(sb.WhereClause).Where(ub.Equal("deleted", 0),)sql, args = ub.Build()fmt.Println(sql)fmt.Println(args)Output:SELECT level FROM users WHERE id = ?[1234]UPDATE users SET level = level + ? WHERE id = ? AND deleted = ?[10 1234 0]
func (*WhereClause)AddWhereExpr¶added inv1.27.0
func (wc *WhereClause) AddWhereExpr(args *Args, andExpr ...string) *WhereClause
AddWhereExpr adds an AND expression to WHERE clause with the specified arguments.
Example¶
// WhereClause can be used as a standalone builder to build WHERE clause.// It's recommended to use it with Cond.whereClause := NewWhereClause()cond := NewCond()whereClause.AddWhereExpr(cond.Args,cond.In("name", "Charmy", "Huan"),cond.LessEqualThan("level", 10),)// Set the flavor of the WhereClause to PostgreSQL.whereClause.SetFlavor(PostgreSQL)sql, args := whereClause.Build()fmt.Println(sql)fmt.Println(args)// Use this WhereClause in another builder.sb := MySQL.NewSelectBuilder()sb.Select("name", "level").From("users")sb.WhereClause = whereClause// The flavor of sb overrides the flavor of the WhereClause.sql, args = sb.Build()fmt.Println(sql)fmt.Println(args)Output:WHERE name IN ($1, $2) AND level <= $3[Charmy Huan 10]SELECT name, level FROM users WHERE name IN (?, ?) AND level <= ?[Charmy Huan 10]
func (*WhereClause)Build¶added inv1.27.0
func (wc *WhereClause) Build() (sqlstring, args []interface{})
Build returns compiled WHERE clause string and args.
func (*WhereClause)BuildWithFlavor¶added inv1.27.0
func (wc *WhereClause) BuildWithFlavor(flavorFlavor, initialArg ...interface{}) (sqlstring, args []interface{})
BuildWithFlavor builds a WHERE clause with the specified flavor and initial arguments.
func (*WhereClause)Flavor¶added inv1.32.0
func (wc *WhereClause) Flavor()Flavor
Flavor returns flavor of clause
func (*WhereClause)SetFlavor¶added inv1.27.0
func (wc *WhereClause) SetFlavor(flavorFlavor) (oldFlavor)
SetFlavor sets the flavor of compiled sql.When the WhereClause belongs to a builder, the flavor of the builder will be used when building SQL.