rushia

package module
v3.0.1 Latest Latest
Warning

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

Go to latest
Published: Oct 25, 2021 License: MIT Imports: 5 Imported by: 1

README

Rushia 台灣正體 GoDoc Coverage Status Build Status Go Report Card

A MySQL query builder that's way- better than most the ORM that written in Golang. Flexible and no struct tags needed. The original idea was from PHP-MySQLi-Database-Class and Laravel Query Builder with extra functions.

This is a query builder without any database connection implmentation, fits for any library as base.

Features

  • Fully functional.
  • Easy to use.
  • SQL query builder.
  • Table migration.
  • Struct mapping.
  • Method chaining.
  • Sub query supported.
  • Prepared Statement supported to prevent 99.9% of SQL injection.

Why?

Gorm is a famous ORM in Golang community, it's really good to use until you meet the JOINs with complex quries. Rushia solved the problem by making a better query builder and omits the dependency with structs.

Installation

Install the package via go get command.

$ go get github.com/teacat/rushia/v3

Usage

Rushia is easy to use, it's kinda like a SQL query but simplized.

Create query

A basic query starts from NewQuery(...) with a table name or a sub query. A complex example with sub query will be mentioned in the later chapters.

q := rushia.NewQuery("Users")
Copy query

By default, Rushia creates a pointer query where you will always modify to the same query. To copy the query with existing rules simply use Copy.

a := rushia.NewQuery("Users")
a.Where("Type = ?", "VIP")

b := a.Copy()
b.Where("Name = ?", "YamiOdymel")

Build(a.Select())
// Equals: SELECT * FROM Users WHERE Type = ?
Build(b.Select())
// Equals: SELECT * FROM Users WHERE Type = ? AND Name = ?
Build query

Execute the Build function when you completed a query with Select, Exists, Replace, Update, Delete... etc. To get the generated query and the params.

query, params := rushia.Build(rushia.NewQuery("Users").Select())
// Equals: SELECT * FROM Users
Use with the other libraries

Since Rushia is just a SQL Builder, you are able to use it with any other database execution libraries. For example with jmoiron/sqlx:

// Initialize a SQLX connection.
db, err := sqlx.Open("mysql", "root:password@tcp(localhost:3306)/db")

// Build the query via Rushia.
q := rushia.NewQuery("Users").Where("Username = ?", "YamiOdymel").Select()
query, params := rushia.Build(q)

// Pass the query and the parameters to SQLX to execute.
rows, err := db.Query(query, params...)
// Equals: SELECT * FROM Users WHERE Username = ?

Or go-gorm/gorm if you like:

// Initialize a Gorm connection.
db, err := gorm.Open(mysql.Open("root:password@tcp(localhost:3306)/db"), &gorm.Config{})

// Build the query via Rushia.
q := rushia.NewQuery("Users").Where("Username = ?", "YamiOdymel").Select()
query, params := rushia.Build(q)

// Pass the query and the parameters to Gorm to execute.
db.Raw(query, params...).Scan(&myUser)
// Equals: SELECT * FROM Users WHERE Username = ?
Struct mapping

You are able to pass a struct to Insert or Update functions and it will be automatically applies the field names and the values into the query.

But be careful! It won't converts the CamelCase field names into snake_cases.

type User struct {
	Username string
	Password string
}
u := User{
	Username: "YamiOdymel",
	Password: "test",
}
rushia.NewQuery("Users").Insert(u)
// Equals: INSERT INTO Users (Username, Password) VALUES (?, ?)
Struct tag

You could omit or rename a field by specify the rushia struct tag.

type User struct {
	Username string `rushia:"-"`
	RealName string `rushia:"real_name"`
	Password string
}
u := User{
	Username: "YamiOdymel",
	RealName: "洨洨安",
	Password: "test",
}
rushia.NewQuery("Users").Insert(u)
// Equals:INSERT INTO Users (real_name, Password) VALUES (?, ?)
Omit

Ignore the fields in the SQL query by using Omit.

type User struct {
	Username string
	Password string
	Age      int    `rushia:"my_age"`
}
u := User{
	Username: "YamiOdymel",
	Password: "test",
	Age     : "32"
}
rushia.NewQuery("Users").Omit("Username", "my_age").Insert(u)
// Equals: INSERT INTO Users (Password) VALUES (?)
Insert

Rushia provides a shorthand H alias, stands for map[string]interface{}. It's the same as gin.H. You can pass a struct or a H, H into a Insert query.

rushia.NewQuery("Users").Insert(rushia.H{
	"Username": "YamiOdymel",
	"Password": "test",
})
// Equals: INSERT INTO Users (Username, Password) VALUES (?, ?)

rushia.NewQuery("Users").Insert(map[string]interface{
	"Username": "YamiOdymel",
	"Password": "test",
})
// Equals: INSERT INTO Users (Username, Password) VALUES (?, ?)
Insert multiple

By passing a []H or []map[string]interface{} to insert multiple values at once.

data := []H{
	{
		"Username": "YamiOdymel",
		"Password": "test",
	}, {
		"Username": "Karisu",
		"Password": "12345",
	},
}
rushia.NewQuery("Users").Insert(data)
// Equals: INSERT INTO Users (Username, Password) VALUES (?, ?), (?, ?)
Replace

The usage Replace is the same as Insert but it deletes the duplicated data and insert a new one. It's dangerous for any data that contains foregin keys. To be safe, use OnDuplicate (ON DUPLICATE KEY UPDATE) instead.

rushia.NewQuery("Users").Replace(rushia.H{
	"Username": "YamiOdymel",
	"Password": "test",
})
// Equals: REPLACE INTO Users (Username, Password) VALUES (?, ?)
On duplicate

Rushia supports ON DUPLICATE KEY UPDATE to update the specified data when it's duplicated on insertion. It's like Replace but it won't delete the duplicated data but update it instead.

rushia.NewQuery("Users").As("New").OnDuplicate(rushia.H{
	"UpdatedAt": rushia.NewExpr("New.UpdatedAt"),
}).Insert(rushia.H{
	"Username":  "YamiOdymel",
	"UpdatedAt": rushia.NewExpr("NOW()"),
})
// Equals: INSERT INTO Users (Username, UpdatedAt) VALUES (?, NOW()) AS New ON DUPLICATE KEY UPDATE UpdatedAt = New.UpdatedAt

rushia.NewQuery("Users").OnDuplicate(rushia.H{
	"UpdatedAt": rushia.NewExpr("VALUES(UpdatedAt)"),
}).Insert(rushia.H{
	"Username":  "YamiOdymel",
	"UpdatedAt": rushia.NewExpr("NOW()"),
})
// CAUTION! `VALUES` has been deprecated since MySQL 8.0.20! Use the above example instead!
// Equals: INSERT INTO Users (Username, UpdatedAt) VALUES (?, NOW()) ON DUPLICATE KEY UPDATE UpdatedAt = VALUES(UpdatedAt)
Expression

By using NewExpr to create an Expression, you can represent a complex value that accepts a raw query, and the parameters to create functions such as: SHA1() or NOW() and intervals.

rushia.NewQuery("Users").Insert(rushia.H{
	"Username":  "YamiOdymel",
	"Password":  rushia.NewExpr("SHA1(?)", "secretpassword+salt"),
	"Expires":   rushia.NewExpr("NOW() + INTERVAL 1 YEAR"),
	"CreatedAt": rushia.NewExpr("NOW()"),
})
// Equals: INSERT INTO Users (Username, Password, Expires, CreatedAt) VALUES (?, SHA1(?), NOW() + INTERVAL 1 YEAR, NOW())
Limit

Limit limits the rows to process (Select, Update, Delete). Only the first 10 rows will be affected if it was set to 10. If 10, 20 was specified, it will skip the first 10 results and process the next 20 results.

rushia.NewQuery("Users").Limit(10).Update(data)
// Equals: UPDATE Users SET ... LIMIT 10

rushia.NewQuery("Users").Limit(10, 20).Select(data)
// Equals: SELECT * from Users LIMIT 10, 20
Offset

The usage of Offset works a bit like Limit but opposite arguments. If 10, 20 was specified, it skips the first 20 results and deal with the rest 10 results.

rushia.NewQuery("Users").Offset(10, 20).Select()
// Equals: SELECT * from Users LIMIT 10 OFFSET 20
Paginate

Paginate is human-friendly, the argument works as page, count. With 1, 20 it fetches the first 20 results, with 2, 20 it fetches the other 20 results from page 2 (basically from 21 to 40).

rushia.NewQuery("Users").Paginate(1, 20).Select()
// Equals: SELECT * from Users LIMIT 0, 20

rushia.NewQuery("Users").Paginate(2, 20).Select()
// Equals: SELECT * from Users LIMIT 20, 20
Update

To update a data in Rushia is easy as a rocket launch (wat? (todo: update this description later)).

rushia.NewQuery("Users").Where("Username = ?", "YamiOdymel").Update(rushia.H{
	"Username": "Karisu",
	"Password": "123456",
})
// Equals: UPDATE Users SET Username = ?, Password = ? WHERE Username = ?
Patch

By using Patch, it's possible to ignore the zero value fields while updating.

rushia.NewQuery("Users").Where("Username = ?", "YamiOdymel").Patch(rushia.H{
	"Age": 0,
	"Username": "",
	"Password": "123456",
})
// Equals: UPDATE Users SET Password = ? WHERE Username = ?

With Exclude, you can also exclude the fields to force it update even if it's a zero value (e.g. false, 0). Passing strings as column names to exclude, and reflect.Kind to exclude by data types.

Any fields that was excluded will still be updated even if it's a zero value.

rushia.NewQuery("Users").Where("Username = ?", "YamiOdymel").Exclude("Username", reflect.Int).Patch(rushia.H{
	"Age":      0,
	"Username": "",
	"Password": "123456",
})
// Equals: UPDATE Users SET Age = ?, Password = ?, Username = ? WHERE Username = ?
Delete

Deletes everything! Remember to add a condition to prevent it really deletes everything.

rushia.NewQuery("Users").Where("ID = ", 1).Delete()
// Equals: DELETE FROM Users WHERE ID = ?
Select

Use Select to get the data.

rushia.NewQuery("Users").Select()
// Equals: SELECT * FROM Users
Specify columns

Specify the columns to select in the Select arguments, It colud also be a expression.

rushia.NewQuery("Users").Select("Username", "Nickname")
// Equals: SELECT Username, Nickname FROM Users

rushia.NewQuery("Users").Select(rushia.NewExpr("COUNT(*) AS Count"))
// Equals: SELECT COUNT(*) AS Count FROM Users
Select One

To get a single row data, use SelectOne. It's a shorthand for .Limit(1).Select(...).

rushia.NewQuery("Users").SelectOne("Username")
// Equals: SELECT Username FROM Users LIMIT 1
Distinct

Specifing Distinct to eliminate the duplicate rows while fetching the data.

rushia.NewQuery("Products").Distinct().Select()
// Equals: SELECT DISTINCT * FROM Products
Union

Union or UnionAll allows you to merge the data between different table selections.

locationQuery := rushia.NewQuery("Locations").Select()

rushia.NewQuery("Users").Union(locationQuery).Select()
// Equals: SELECT * FROM Users UNION SELECT * FROM Locations

rushia.NewQuery("Users").UnionAll(locationQuery).Select()
// Equals: SELECT * FROM Users UNION ALL SELECT * FROM Locations
Select exists

To execute SELECT EXISTS by calling Exists.

rushia.NewQuery("Users").Where("Username = ?", "YamiOdymel").Exists()
// Equals: SELECT EXISTS(SELECT * FROM Users WHERE Username = ?)
Table alias

As assign an alias to the query, it's useful if you are creating a sub query. In a joining or common scenario, use NewAlias instead.

rushia.NewQuery(NewQuery("Users").Select()).As("Result").Where("Username = ?", "YamiOdymel").Select())
// Equals: SELECT * FROM (SELECT * FROM Users) AS Result WHERE Username = ?

rushia.NewQuery(rushia.NewAlias("UserFriendRelationships", "relations")).Where("relations.ID = ?", 5).Select()
// Equals: SELECT * FROM UserFriendRelationships AS relations WHERE relations.ID = ?
Raw Query

Rushia provides you the most 80% things you will use, but if you are in the bad luck to request for the rest 20%, the only hope is to use Raw Query.

A raw query does also support the prepared statement, to replace the value as ? to prevent the SQL injection.

NewRawQuery is the same as NewQuery that required to be Build, and the helper functions such as: Limit, OrderBy...etc, are not able to be used.

q := rushia.NewRawQuery("SELECT * FROM Users WHERE ID >= ?", 10)
Conditions

To define a WHERE or HAVING condition in Rushia is a piece of cake!

SQL Query Usage
Column = ?
Column > ?
.Where("Column = ?", "Value")
.Where("Column > ?", "Value")
Column = Column .Where("Column = Column")
Column IN (?, ?)
Column NOT IN (?, ?)
.Where("Column IN (?, ?)", "A", "B")
.Where("Column NOT IN (?, ?)", "A", "B")
Column IN (?, ?) .Where("Column IN ?", []interface{}{"A", "B"})
Column BETWEEN ? AND ?
Column NOT BETWEEN ? AND ?
.Where("Column BETWEEN ? AND ?", 1, 20)
.Where("Column NOT BETWEEN ? AND ?", 1, 20)
Column IS NULL
Column IS NOT NULL
.Where("Column IS NULL")
.Where("Column IS NOT NULL")
Column EXISTS Query
Column NOT EXISTS Query
.Where("Column EXISTS ?", subQuery)
.Where("Column NOT EXISTS ?", subQuery)
Column LIKE ?
Column NOT LIKE ?
.Where("Column LIKE ?", "Value")
.Where("Column NOT LIKE ?", "Value")
(Column = Column OR Column = ?) .Where("(Column = Column OR Column = ?)", "Value")

The condition functions has it's own transform for Where, OrWhere, Having, OrHaving, JoinWhere, OrJoinWhere.

rushia.NewQuery("Users").Where("ID = ?", 1).Where("Username = ?", "admin").Select()
// Equals: SELECT * FROM Users WHERE ID = ? AND Username = ?

rushia.NewQuery("Users").Having("ID = ?", 1).Having("Username = ?", "admin").Select()
// Equals: SELECT * FROM Users HAVING ID = ? AND Username = ?

rushia.NewQuery("Users").Where("ID != CompanyID").Where("DATE(CreatedAt) = DATE(LastLogin)").Select()
// Equals: SELECT * FROM Users WHERE ID != CompanyID AND DATE(CreatedAt) = DATE(LastLogin)
Expanded Prepared Statment

You can easily avoid the 99.9% SQL Injection by using Prepared Statement.

In Rushia, it's possible to pass a slice (e.g: []interface{}, []int...etc) into a single ? parepared statement, and it will be automatically expanded to multiple prepared statements.

rushia.NewQuery("Users").Where("ID IN ?", []interface{}{"A", "B", "C"}).Select()
// Equals: SELECT * FROM Users WHERE ID IN (?, ?, ?)
Escaped Values

The same usage as ?? double question marks in mysqljs/mysql package, it's possible to escape the values with backticks (`) by using ??. It's useful for column names.

var ColumnUserID = "ID"
rushia.NewQuery("Users").Where("?? = ?", ColumnUserID, 3).Select()
// Equals: SELECT * FROM Users WHERE `ID` = ?
Order

Ordering is also supported in Rushia and can be used with functions.

rushia.NewQuery("Users").OrderBy("ID ASC").OrderBy("Login DESC").OrderBy("RAND()").Select()
// Equals: SELECT * FROM Users ORDER BY ID ASC, Login DESC, RAND()
Order by field

Or ordering by custom field values:

rushia.NewQuery("Users").OrderByField("UserGroup", "SuperUser", "Admin", "Users").Select()
// Equals: SELECT * FROM Users ORDER BY FIELD (UserGroup, ?, ?, ?)
Group by

The result can also be grouped with GroupBy.

rushia.NewQuery("Users").GroupBy("Name").Select()
// Equals: SELECT * FROM Users GROUP BY Name
Table joins

Rushia supports multiple ways to join the tables, such as: InerrJoin, LeftJoin, RightJoin, NaturalJoin, CrossJoin. While joining, the last argument is always a raw condition and colud be useful.

rushia.
	NewQuery("Products").
	LeftJoin("Users", "Products.TenantID = Users.TenantID").
	Select("Users.Name", "Products.ProductName")
// Equals: SELECT Users.Name, Products.ProductName FROM Products AS Products LEFT JOIN Users AS Users ON (Products.TenantID = Users.TenantID)

rushia.
	NewQuery("Products").
	LeftJoin("Users", "Products.TenantID = ?", 3).
	Select("Users.Name", "Products.ProductName")
// Equals: SELECT Users.Name, Products.ProductName FROM Products AS Products LEFT JOIN Users AS Users ON (Products.TenantID = ?)

Or just omit the condition and define it later in the function chaining.

rushia.
	NewQuery("Products").
	LeftJoin("Users").
	JoinWhere("Products.TenantID = Users.TenantID")
	Select("Users.Name", "Products.ProductName")
// Equals: SELECT Users.Name, Products.ProductName FROM Products AS Products LEFT JOIN Users AS Users ON (Products.TenantID = Users.TenantID)
Join condition

With JoinWhere or OrJoinWhere to expand the conditions for the table joins. The condition will always to be added into the latest joined table.

rushia.
	NewQuery("Products").
	LeftJoin("Users", "Products.TenantID = Users.TenantID").
	OrJoinWhere("Users.TenantID = ?", 5).
	Select("Users.Name", "Products.ProductName")
// Equals: SELECT Users.Name, Products.ProductName FROM Products AS Products LEFT JOIN Users AS Users ON (Products.TenantID = Users.TenantID OR Users.TenantID = ?)
Sub query

Rushia supports nested query which is called Sub Query. Use a query as a value to make it sub query.

subQuery := rushia.NewQuery("VIPUsers").Select("UserID")

rushia.NewQuery("Users").Where("ID IN ?", subQuery).Select()
// Equals: SELECT * FROM Users WHERE ID IN (SELECT UserID FROM VIPUsers)
Sub query insertion

To insert a value from a sub query, simply use the query as a value and make sure the sub query only returns one column and one row as result.

subQuery := rushia.NewQuery("Users").Where("ID = ?", 6).SelectOne("Name")

rushia.NewQuery("Products").Insert(rushia.H{
	"ProductName": "測試商品",
	"UserID":      subQuery,
	"LastUpdated": rushia.NewExpr("NOW()")
})
// Equals: INSERT INTO Products (ProductName, UserID, LastUpdated) VALUES (?, (SELECT Name FROM Users WHERE ID = 6 LIMIT 1), NOW())
Sub query joining

Join a table from a sub query is possible, but requires to assign an alias to the sub query by using As.

subQuery := rushia.NewQuery("Users").As("Users").Where("Active = ?", 1).Select()

rushia.
	NewQuery("Products").
	LeftJoin(subQuery, "Products.UserID = Users.ID").
	Select("Users.Username", "Products.ProductName")
// Equals: SELECT Users.Username, Products.ProductName FROM Products AS Products LEFT JOIN (SELECT * FROM Users WHERE Active = ?) AS Users ON Products.UserID = Users.ID
Sub query swapping

Passing a sub query to a raw query or an expression will automatically looking for the prepared statement ? to replace as a built sub query.

subQuery := rushia.NewQuery("Locations").Select()
rawQuery := rushia.NewRawQuery("SELECT UserID FROM Users WHERE EXISTS (?)", subQuery)

NewQuery("Products").Where("EXISTS ?", rawQuery).Select()
// Equals: SELECT * FROM Products WHERE EXISTS (SELECT UserID FROM Users WHERE EXISTS (SELECT * FROM Locations))
Set query options

You can set the query options with Rushia.

rushia.NewQuery("Users").SetQueryOption("FOR UPDATE").Select()
// Equals: SELECT * FROM Users FOR UPDATE

rushia.NewQuery("Users").SetQueryOption("SQL_NO_CACHE").Select()
// Equals: SELECT SQL_NO_CACHE * FROM Users

rushia.NewQuery("Users").SetQueryOption("LOW_PRIORITY", "IGNORE").Insert(data)
// Gives: INSERT LOW_PRIORITY IGNORE INTO Users ...

Complex query example

jobHistories := rushia.NewQuery("JobHistories").
	Where("DepartmentID BETWEEN ? AND ?", 50, 100).
	Select("JobID")
jobs := rushia.NewQuery("Jobs").
	Where("JobID IN ?", jobHistories).
	GroupBy("JobID").
	Select("JobID", "AVG(MinSalary) AS MyAVG")
maxAverage := rushia.NewQuery(jobs).
	As("SS").
	Select("MAX(MyAVG)")
employees := rushia.NewQuery("Employees").
	GroupBy("JobID").
	Having("AVG(Salary) < ?", maxAverage).
	Select("JobID", "AVG(Salary)")

// Equals:
// SELECT JobID,
//        AVG(Salary)
// FROM   Employees
// HAVING AVG(Salary) < (SELECT MAX(MyAVG)
//                       FROM   (SELECT JobID,
//                                      AVG(MinSalary) AS MyAVG
//                               FROM   Jobs
//                               WHERE  JobID IN (SELECT JobID
//                                                FROM   JobHistories
//                                                WHERE  DepartmentID BETWEEN 50
//                                                       AND 100
//                                               )
//                               GROUP  BY JobID) AS SS)
// GROUP  BY job_id;

agents := rushia.NewQuery("Agents").
	Where("Commission < ?", 0.12).
	Select()
customers := rushia.NewQuery("Customers").
	Where("Grade = ?", 3).
	Where("CustomerCountry <> ?", "India").
	Where("OpeningAmount < ?", 7000).
	Where("EXISTS ?", agents).
	Select("OutstandingAmount")
orders := rushia.NewQuery("Orders").
	Where("OrderAmount > ?", 2000).
	Where("OrderDate < ?", "01-SEP-08").
	Where("AdvanceAmount < ANY (?)", customers).
	Select("OrderNum", "OrderDate", "OrderAmount", "AdvanceAmount")

// Equals:
// SELECT OrderNum,
//        OrderDate,
//        OrderAmount,
//        AdvanceAmount
// FROM   Orders
// WHERE  OrderAmount > 2000
//        AND OrderDate < '01-SEP-08'
//        AND AdvanceAmount < ANY (SELECT OutstandingAmount
//                                 FROM   Customers
//                                 WHERE  Grade = 3
//                                        AND CustomerCountry <> 'India'
//                                        AND OpeningAmount < 7000
//                                        AND EXISTS (SELECT *
//                                                    FROM   Agents
//                                                    WHERE  Commission < 0.12));

References

Let's see what inspired Rushia.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrQueryTypeUnspecified
	ErrQueryTypeUnspecified = errors.New("rushia: query type unspecified")
)

Functions

func Build

func Build(q *Query) (query string, params []interface{})

Build builds the Query.

func NewAlias

func NewAlias(table string, alias string) string

NewAlias creates an alias for a table.

Types

type Expr

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

Expr

func NewExpr

func NewExpr(query string, params ...interface{}) *Expr

NewExpr creates an Expression that accepts raw query and the parameters. Could be useful as the value if you are representing a complex query.

type H

type H map[string]interface{}

H

type Query

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

Query

func NewQuery

func NewQuery(table interface{}) *Query

NewQuery creates a Query based on a table name or a sub query.

func NewRawQuery

func NewRawQuery(q string, params ...interface{}) *Query

NewRawQuery creates a Query based on the passed in raw query and the parameters.

func (*Query) As

func (q *Query) As(alias string) *Query

As creates an alias for current query.

func (*Query) ClearLimit

func (q *Query) ClearLimit() *Query

func (*Query) Copy

func (q *Query) Copy() *Query

Copy creates a copy of the current query, so you are able to make changes and it won't modify the original query.

func (*Query) CrossJoin

func (q *Query) CrossJoin(table interface{}, conditions ...interface{}) *Query

CrossJoin creates a `CROSS JOIN` to join a table.

func (*Query) Delete

func (q *Query) Delete() *Query

Delete creates a `DELETE` query to delete the data. Make sure you are using it with `WHERE` condition to not delete all the data.

func (*Query) Distinct

func (q *Query) Distinct() *Query

Distinct adds the `DISTINCT` option to the query.

func (*Query) Exclude

func (q *Query) Exclude(fields ...interface{}) *Query

Exclude excludes the specified fields, data types while patching with `Patch` method. Pass string values as field names, and `reflect.Kind` as data types to exclude. While patching, all the zero values will be ignored unless it's in the exclude list.

func (*Query) Exists

func (q *Query) Exists() *Query

Exists creates a `SELECT EXISTS` query, returns a result if the query does match a row.

func (*Query) GroupBy

func (q *Query) GroupBy(columns ...string) *Query

GroupBy creates a `GROUP BY` option to the query.

func (*Query) Having

func (q *Query) Having(query string, args ...interface{}) *Query

Having creates a `HAVING` condition.

func (*Query) InnerJoin

func (q *Query) InnerJoin(table interface{}, conditions ...interface{}) *Query

InnerJoin creates a `INNER JOIN` to join a table.

func (*Query) Insert

func (q *Query) Insert(v interface{}) *Query

Insert creates a `INSERT INTO` query with specified data. It inserts a data to the database.

func (*Query) InsertSelect

func (q *Query) InsertSelect(qu *Query, columns ...interface{}) *Query

InsertSelect creates a `INSERT SELECT` query, it works a bit like table copy. The insert data is from another selection, pass a `SELECT` query to the first argument.

func (*Query) JoinWhere

func (q *Query) JoinWhere(query string, args ...interface{}) *Query

JoinWhere creates the `AND` joining condition for latest table join.

func (*Query) LeftJoin

func (q *Query) LeftJoin(table interface{}, conditions ...interface{}) *Query

LeftJoin creates a `LEFT JOIN` to join a table.

func (*Query) Limit

func (q *Query) Limit(from int, count ...int) *Query

Limit creates `LIMIT` option to the query.

func (*Query) NaturalJoin

func (q *Query) NaturalJoin(table interface{}, conditions ...interface{}) *Query

NaturalJoin creates a `NATURAL JOIN` to join a table.

func (*Query) Offset

func (q *Query) Offset(count int, offset int) *Query

Offset creates `LIMIT OFFSET` option to the query.

func (*Query) Omit

func (q *Query) Omit(fields ...string) *Query

Omit omits specified fields in the data so it won't be insert/update into the database.

func (*Query) OnDuplicate

func (q *Query) OnDuplicate(v H) *Query

OnDuplicate creates `ON DUPLICATE KEY UPDATE` query, works when inserting a duplicated data, the data will be automatically updated to the new value.

func (*Query) OrHaving

func (q *Query) OrHaving(query string, args ...interface{}) *Query

OrHaving creates a `HAVING OR` condition.

func (*Query) OrJoinWhere

func (q *Query) OrJoinWhere(query string, args ...interface{}) *Query

OrJoinWhere creates the `OR` joining condition for latest table join.

func (*Query) OrWhere

func (q *Query) OrWhere(query string, args ...interface{}) *Query

OrWhere creates a `WHERE OR` condition.

func (*Query) OrderBy

func (q *Query) OrderBy(columns ...string) *Query

OrderBy creates a `ORDER BY` option to the query.

func (*Query) OrderByField

func (q *Query) OrderByField(field string, values ...interface{}) *Query

OrderByField creates a `ORDER BY FIELD` option to the query.

func (*Query) Paginate

func (q *Query) Paginate(page int, limit int) *Query

Paginate is a human-friendly `LIMIT` option.

func (*Query) Patch

func (q *Query) Patch(v interface{}) *Query

Patch works the same as `Update` but ignores the zero value. The zero value fields won't be updated unless it's in exclude list, to define the list, call `Exclude`.

func (*Query) Replace

func (q *Query) Replace(v interface{}) *Query

Replace creates a `REPLACE INTO` query with specified data. It deletes the original data and creates a new one instead, prettry dangerous if the data contains a foreign key.

func (*Query) RightJoin

func (q *Query) RightJoin(table interface{}, conditions ...interface{}) *Query

RightJoin creates a `RIGHT JOIN` to join a table.

func (*Query) Select

func (q *Query) Select(columns ...interface{}) *Query

Select creates a `SELECT` query with specified columns, can be empty for select everything (`*`). It fetches the data from database.

func (*Query) SelectOne

func (q *Query) SelectOne(columns ...interface{}) *Query

SelectOne works the same as `Select` but returns only one row as result. It's the combination of `.Limit(1).Select()`.

func (*Query) SetQueryOption

func (q *Query) SetQueryOption(option string) *Query

SetQueryOption sets the query options, and it will be automatically be appended after or before the query.

func (*Query) Union

func (q *Query) Union(qu *Query) *Query

Union creates a `UNION` query that connects two tables. It groups the result from multiple tables but eliminates the duplicates.

func (*Query) UnionAll

func (q *Query) UnionAll(qu *Query) *Query

UnionAll creates a `UNION ALL` query that connects two tables. It groups the result from multiple tables and it keeps the duplicates.

func (*Query) Update

func (q *Query) Update(v interface{}) *Query

Update creates a `UPDATE` query with specified data. It updates the data with new data, normally use with `WHERE` condition.

func (*Query) Where

func (q *Query) Where(query string, args ...interface{}) *Query

Where creates a `WHERE` condition.

Jump to

Keyboard shortcuts

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