eorm

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Dec 7, 2022 License: Apache-2.0 Imports: 13 Imported by: 1

README

EORM

codecov

简单的 ORM 框架。

使用注意事项(技术选型前必读)

丑话说前头。

  • eorm 支持的字段类型:这是指在 Go 语言层面上支持的类型,eorm 本身并不关心数据库表里面定义的类型;
Go 版本

请使用 Go 1.18 以上版本。

SQL 2003 标准

理论上来说,我们计划支持 SQL 2003 standard. 不过据我们所知,并不是所有的数据库都支持全部的 SQL 2003 标准,所以用户还是需要进一步检查目标数据库的语法。

全中文仓库

这是一个全中文的仓库。这意味着注释、文档和错误信息,都会是中文。介意的用户可以选择别的 ORM 仓库。

但是不必来反馈说希望提供英文版本,我们是不会提供的,因为:

  • 这个仓库目前以及可预测的将来,都不会有外国人使用。很多国内开发者的开原仓库提供了英文选项但是实际上英文用户数量感人,我就不想做这种性价比低的事情;
  • 双语言会导致英文用户有一些不切实际的期望,比如说在 issues 和 discussions 里面都使用英文交流。但是这对于我的目标来说,也是不现实的。因为很多国内开发者不具备这种英文能力,而且这些开发者非常倔强,即便我们一再强调请使用英文,他们也会固执使用中文。因此我索性将这个搞成全中文仓库,一了百了;
  • 中文终究是我的母语,所以使用中文的表达能力更加准确;
  • 翻译软件非常发达,真有英语用户要用,可以自己找翻译软件;
社区组织和讨论

短时间内,我不会组建任何的微信群,QQ 群或者钉钉群之类的即时通讯群。

我注意到很多开源仓库都会组织类似的群,但是这种群有利有弊,而且对于项目本身来说是弊大于利的。组建了不同的群之后会导致问题讨论被切割到不同的群里面。例如某个群讨论了 A 问题,其它群完全看不到。

另外一个原因就是,因为即时通讯过于便捷,会给维护者带来庞大的维护压力。用户可能期望自己的所有答案都能从群里得到解答,因此不愿意自己花时间去读文档,读注释,读例子。在这种情况下,他们会频繁艾特维护者,并希望维护者能够实时给出详细回答。而实际情况是,一般的小项目维护者可能只有两三个人,所以没有足够的精力来维护这种群。

我想要的社区是大家统一在 github 下,利用 issue 和 discussion 来讨论问题。这样别的用户都可以搜索到所有的讨论。

加入我们

我们欢迎任何人给我们提合并请求,但是我们希望合并请求能够做到:

  • 一个合并请求一个 Commit ID
  • 自己要先确保合并请求能够通过 CI
  • 我们使用 uber 的代码风格

我们尤其欢迎两类人:

  • 新特性试用者
  • 长期稳定贡献者
设置开发环境

如果你是 Windows 用户,那么我们建议你使用 WSL,因为这个仓库会使用到一个 Unix 命令来帮助构建、测试等。

安装 golangci-lint

参考 Install golangci-lint

设置 pre-push github hook

.github/pre-push 复制到本仓库的 .git 目录下

Documentation

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoRows 代表没有找到数据
	ErrNoRows = errs.ErrNoRows
)

哨兵错误,或者说预定义错误,谨慎添加

Functions

func Columns

func Columns(cs ...string) columns

Columns specify columns

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(Columns("Id", "Age")).From(tm).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: SELECT `id`,`age` FROM `test_model`;
Args: []

Types

type Aggregate

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

Aggregate represents aggregate expression, including AVG, MAX, MIN...

func Avg

func Avg(c string) Aggregate

Avg represents AVG

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Avg("Age").As("avg_age")).From(&TestModel{}).Build()
fmt.Println(query.SQL)
Output:

SELECT AVG(`age`) AS `avg_age` FROM `test_model`;

func Count

func Count(c string) Aggregate

Count represents COUNT

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Count("Age")).From(&TestModel{}).Build()
fmt.Println(query.SQL)
Output:

SELECT COUNT(`age`) FROM `test_model`;

func Max

func Max(c string) Aggregate

Max represents MAX

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Max("Age")).From(&TestModel{}).Build()
fmt.Println(query.SQL)
Output:

SELECT MAX(`age`) FROM `test_model`;

func Min

func Min(c string) Aggregate

Min represents MIN

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Min("Age")).From(&TestModel{}).Build()
fmt.Println(query.SQL)
Output:

SELECT MIN(`age`) FROM `test_model`;

func Sum

func Sum(c string) Aggregate

Sum represents SUM

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Sum("Age")).From(&TestModel{}).Build()
fmt.Println(query.SQL)
Output:

SELECT SUM(`age`) FROM `test_model`;

func (Aggregate) As

func (a Aggregate) As(alias string) Selectable

As specifies the alias

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Avg("Age").As("avg_age")).From(&TestModel{}).Build()
fmt.Println(query.SQL)
Output:

SELECT AVG(`age`) AS `avg_age` FROM `test_model`;

func (Aggregate) EQ

func (a Aggregate) EQ(val interface{}) Predicate

func (Aggregate) GT

func (a Aggregate) GT(val interface{}) Predicate

GT >

func (Aggregate) GTEQ

func (a Aggregate) GTEQ(val interface{}) Predicate

GTEQ >=

func (Aggregate) LT

func (a Aggregate) LT(val interface{}) Predicate

LT <

func (Aggregate) LTEQ

func (a Aggregate) LTEQ(val interface{}) Predicate

LTEQ <=

func (Aggregate) NEQ

func (a Aggregate) NEQ(val interface{}) Predicate

type Assignable

type Assignable interface {
	// contains filtered or unexported methods
}

Assignable represents that something could be used as "assignment" statement

func AssignColumns

func AssignColumns(entity interface{}, filter func(typ reflect.StructField, val reflect.Value) bool) []Assignable

AssignColumns will check all columns and then apply the filter function. If the returned value is true, this column will be updated.

func AssignNotNilColumns

func AssignNotNilColumns(entity interface{}) []Assignable

AssignNotNilColumns uses the non-nil value to construct the Assignable instances.

Example
db := memoryDB()
query, _ := NewUpdater[TestModel](db).Set(AssignNotNilColumns(&TestModel{Id: 13})...).Build()
fmt.Println(query.string())
Output:

SQL: UPDATE `test_model` SET `id`=?,`first_name`=?,`age`=?;
Args: []interface {}{13, "", 0}

func AssignNotZeroColumns

func AssignNotZeroColumns(entity interface{}) []Assignable

AssignNotZeroColumns uses the non-zero value to construct the Assignable instances.

Example
db := memoryDB()
query, _ := NewUpdater[TestModel](db).Set(AssignNotZeroColumns(&TestModel{Id: 13})...).Build()
fmt.Println(query.string())
Output:

SQL: UPDATE `test_model` SET `id`=?;
Args: []interface {}{13}

type Assignment

type Assignment binaryExpr

Assignment represents assignment statement

func Assign

func Assign(column string, value interface{}) Assignment
Example
db := memoryDB()
tm := &TestModel{}
examples := []struct {
	assign    Assignment
	assignStr string
	wantSQL   string
	wantArgs  []interface{}
}{
	{
		assign:    Assign("Age", 18),
		assignStr: `Assign("Age", 18)`,
		wantSQL:   "UPDATE `test_model` SET `age`=?;",
		wantArgs:  []interface{}{18},
	},
	{
		assign:    Assign("Age", C("Id")),
		assignStr: `Assign("Age", C("Id"))`,
		wantSQL:   "UPDATE `test_model` SET `age`=`id`;",
	},
	{
		assign:    Assign("Age", C("Age").Add(1)),
		assignStr: `Assign("Age", C("Age").Add(1))`,
		wantSQL:   "UPDATE `test_model` SET `age`=`age`+?;",
		wantArgs:  []interface{}{1},
	},
	{
		assign:    Assign("Age", Raw("`age`+`id`+1")),
		assignStr: "Assign(\"Age\", Raw(\"`age`+`id`+1\"))",
		wantSQL:   "UPDATE `test_model` SET `age`=`age`+`id`+1;",
	},
}
for _, exp := range examples {
	query, _ := NewUpdater[TestModel](db).Update(tm).Set(exp.assign).Build()
	fmt.Printf(`
Assignment: %s
SQL: %s
Args: %v
`, exp.assignStr, query.SQL, query.Args)
}
Output:


Assignment: Assign("Age", 18)
SQL: UPDATE `test_model` SET `age`=?;
Args: [18]

Assignment: Assign("Age", C("Id"))
SQL: UPDATE `test_model` SET `age`=`id`;
Args: []

Assignment: Assign("Age", C("Age").Add(1))
SQL: UPDATE `test_model` SET `age`=(`age`+?);
Args: [1]

Assignment: Assign("Age", Raw("`age`+`id`+1"))
SQL: UPDATE `test_model` SET `age`=`age`+`id`+1;
Args: []

type Column

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

Column represents column it could have alias in general, we use it in two ways 1. specify the column in query 2. it's the start point of building complex expression

func C

func C(c string) Column

C specify column

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").EQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: SELECT `id` FROM `test_model` WHERE `id`=?;
Args: [18]

func (Column) Add

func (c Column) Add(val interface{}) MathExpr

Add generate an additive expression

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewUpdater[TestModel](db).Update(tm).Set(Assign("Age", C("Age").Add(1))).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: UPDATE `test_model` SET `age`=(`age`+?);
Args: [1]

func (Column) As

func (c Column) As(alias string) Selectable

As means alias

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id").As("my_id")).From(tm).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: SELECT `id` AS `my_id` FROM `test_model`;
Args: []

func (Column) EQ

func (c Column) EQ(val interface{}) Predicate

EQ =

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").EQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: SELECT `id` FROM `test_model` WHERE `id`=?;
Args: [18]

func (Column) GT

func (c Column) GT(val interface{}) Predicate

GT >

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").GT(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: SELECT `id` FROM `test_model` WHERE `id`>?;
Args: [18]

func (Column) GTEQ

func (c Column) GTEQ(val interface{}) Predicate

GTEQ >=

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").GTEQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: SELECT `id` FROM `test_model` WHERE `id`>=?;
Args: [18]

func (Column) In

func (c Column) In(data ...any) Predicate

In 方法没有元素传入,会被认为是false,被解释成where false这种形式

func (Column) LT

func (c Column) LT(val interface{}) Predicate

LT <

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").LT(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: SELECT `id` FROM `test_model` WHERE `id`<?;
Args: [18]

func (Column) LTEQ

func (c Column) LTEQ(val interface{}) Predicate

LTEQ <=

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").LTEQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: SELECT `id` FROM `test_model` WHERE `id`<=?;
Args: [18]

func (Column) Like

func (c Column) Like(val interface{}) Predicate

Like -> LIKE %XXX 、_x_ 、xx[xx-xx] 、xx[^xx-xx]

func (Column) Multi

func (c Column) Multi(val interface{}) MathExpr

Multi generate a multiplication expression

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewUpdater[TestModel](db).Update(tm).Set(Assign("Age", C("Age").Multi(2))).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: UPDATE `test_model` SET `age`=(`age`*?);
Args: [2]

func (Column) NEQ

func (c Column) NEQ(val interface{}) Predicate

NEQ !=

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewSelector[TestModel](db).Select(C("Id")).From(tm).Where(C("Id").NEQ(18)).Build()
fmt.Printf(`
SQL: %s
Args: %v
`, query.SQL, query.Args)
Output:

SQL: SELECT `id` FROM `test_model` WHERE `id`!=?;
Args: [18]

func (Column) NotIn

func (c Column) NotIn(data ...any) Predicate

NotIn 方法没有元素传入,会被认为是false,被解释成where false这种形式

func (Column) NotLike

func (c Column) NotLike(val interface{}) Predicate

NotLike -> NOT LIKE %XXX 、_x_ 、xx[xx-xx] 、xx[^xx-xx]

type DB

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

DB represents a database

func Open

func Open(driver string, dsn string, opts ...DBOption) (*DB, error)

Open 创建一个 ORM 实例 注意该实例是一个无状态的对象,你应该尽可能复用它

Example
// case1 without DBOption
db, _ := Open("sqlite3", "file:test.db?cache=shared&mode=memory")
fmt.Printf("case1 dialect: %s\n", db.dialect.Name)
Output:

case1 dialect: SQLite

func (*DB) BeginTx

func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)

BeginTx 开启事务

Example
db, _ := Open("sqlite3", "file:test.db?cache=shared&mode=memory")
defer func() {
	_ = db.Close()
}()
tx, err := db.BeginTx(context.Background(), &sql.TxOptions{})
if err == nil {
	fmt.Println("Begin")
}
// 或者 tx.Rollback()
err = tx.Commit()
if err == nil {
	fmt.Println("Commit")
}
Output:

Begin
Commit

func (*DB) Close

func (db *DB) Close() error

func (*DB) Wait

func (db *DB) Wait() error

Wait 会等待数据库连接 注意只能用于测试

type DBOption

type DBOption func(db *DB)

DBOption configure DB

func UseReflection

func UseReflection() DBOption

type Deleter

type Deleter[T any] struct {
	// contains filtered or unexported fields
}

Deleter builds DELETE query

func NewDeleter

func NewDeleter[T any](sess session) *Deleter[T]

NewDeleter 开始构建一个 DELETE 查询

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewDeleter[TestModel](db).From(tm).Build()
fmt.Printf("SQL: %s", query.SQL)
Output:

SQL: DELETE FROM `test_model`;

func (*Deleter[T]) Build

func (d *Deleter[T]) Build() (*Query, error)

Build returns DELETE query

Example
query, _ := NewDeleter[TestModel](memoryDB()).From(&TestModel{}).Build()
fmt.Printf("SQL: %s", query.SQL)
Output:

SQL: DELETE FROM `test_model`;

func (*Deleter[T]) Exec

func (d *Deleter[T]) Exec(ctx context.Context) Result

Exec sql

func (*Deleter[T]) From

func (d *Deleter[T]) From(table interface{}) *Deleter[T]

From accepts model definition

Example
query, _ := NewDeleter[TestModel](memoryDB()).From(&TestModel{}).Build()
fmt.Printf("SQL: %s", query.SQL)
Output:

SQL: DELETE FROM `test_model`;

func (*Deleter[T]) Where

func (d *Deleter[T]) Where(predicates ...Predicate) *Deleter[T]

Where accepts predicates

Example
query, _ := NewDeleter[TestModel](memoryDB()).Where(C("Id").EQ(12)).Build()
fmt.Printf("SQL: %s\nArgs: %v", query.SQL, query.Args)
Output:

SQL: DELETE FROM `test_model` WHERE `id`=?;
Args: [12]

type Executor

type Executor interface {
	Exec(ctx context.Context) Result
}

Executor is used to build a query

type Expr

type Expr interface {
	// contains filtered or unexported methods
}

Expr is the top interface. It represents everything.

type Inserter

type Inserter[T any] struct {
	// contains filtered or unexported fields
}

Inserter is used to construct an insert query More details check Build function

func NewInserter

func NewInserter[T any](sess session) *Inserter[T]

NewInserter 开始构建一个 INSERT 查询

Example
db := memoryDB()
tm := &TestModel{}
query, _ := NewInserter[TestModel](db).Values(tm).Build()
fmt.Printf("SQL: %s", query.SQL)
Output:

SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?);

func (*Inserter[T]) Build

func (i *Inserter[T]) Build() (*Query, error)

Build function build the query notes: - All the values from function Values should have the same type. - It will insert all columns including auto-increment primary key

Example
db := memoryDB()
query, _ := NewInserter[TestModel](db).Values(&TestModel{
	Id:  1,
	Age: 18,
}).Build()
fmt.Printf("case1\n%s", query.string())

query, _ = NewInserter[TestModel](db).Values(&TestModel{}).Build()
fmt.Printf("case2\n%s", query.string())
Output:

case1
SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?);
Args: []interface {}{1, "", 18, (*sql.NullString)(nil)}
case2
SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?);
Args: []interface {}{0, "", 0, (*sql.NullString)(nil)}

func (*Inserter[T]) Columns

func (i *Inserter[T]) Columns(cs ...string) *Inserter[T]

Columns specifies the columns that need to be inserted if cs is empty, all columns will be inserted cs must be the same with the field name in model

Example
db := memoryDB()
query, _ := NewInserter[TestModel](db).Values(&TestModel{
	Id:  1,
	Age: 18,
}).Columns("Id", "Age").Build()
fmt.Printf("case1\n%s", query.string())

query, _ = NewInserter[TestModel](db).Values(&TestModel{
	Id:  1,
	Age: 18,
}, &TestModel{}, &TestModel{FirstName: "Tom"}).Columns("Id", "Age").Build()
fmt.Printf("case2\n%s", query.string())
Output:

case1
SQL: INSERT INTO `test_model`(`id`,`age`) VALUES(?,?);
Args: []interface {}{1, 18}
case2
SQL: INSERT INTO `test_model`(`id`,`age`) VALUES(?,?),(?,?),(?,?);
Args: []interface {}{1, 18, 0, 0, 0, 0}

func (*Inserter[T]) Exec

func (i *Inserter[T]) Exec(ctx context.Context) Result

Exec 发起查询

func (*Inserter[T]) Values

func (i *Inserter[T]) Values(values ...*T) *Inserter[T]

Values specify the rows all the elements must be the same type and users are supposed to passing at least one element

Example
db := memoryDB()
query, _ := NewInserter[TestModel](db).Values(&TestModel{
	Id:  1,
	Age: 18,
}, &TestModel{}).Build()
fmt.Println(query.string())
Output:

SQL: INSERT INTO `test_model`(`id`,`first_name`,`age`,`last_name`) VALUES(?,?,?,?),(?,?,?,?);
Args: []interface {}{1, "", 18, (*sql.NullString)(nil), 0, "", 0, (*sql.NullString)(nil)}

type MathExpr

type MathExpr binaryExpr

func (MathExpr) Add

func (m MathExpr) Add(val interface{}) Expr

func (MathExpr) Multi

func (m MathExpr) Multi(val interface{}) MathExpr

type OrderBy

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

OrderBy specify fields and ASC

func ASC

func ASC(fields ...string) OrderBy

ASC means ORDER BY fields ASC

func DESC

func DESC(fields ...string) OrderBy

DESC means ORDER BY fields DESC

type Predicate

type Predicate binaryExpr

Predicate will be used in Where Or Having

func Not

func Not(p Predicate) Predicate

Not indicates "NOT"

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Columns("Id")).From(&TestModel{Id: 10}).Where(Not(C("Id").EQ(18))).Build()
fmt.Println(query.string())
Output:

SQL: SELECT `id` FROM `test_model` WHERE NOT (`id`=?);
Args: []interface {}{18}

func (Predicate) And

func (p Predicate) And(pred Predicate) Predicate

And indicates "AND"

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Columns("Id")).From(&TestModel{
	Id: 10,
}).Where(C("Id").EQ(18).And(C("Age").GT(100))).Build()
fmt.Println(query.string())
Output:

SQL: SELECT `id` FROM `test_model` WHERE (`id`=?) AND (`age`>?);
Args: []interface {}{18, 100}

func (Predicate) Or

func (p Predicate) Or(pred Predicate) Predicate

Or indicates "OR"

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Columns("Id")).From(&TestModel{
	Id: 10,
}).Where(C("Id").EQ(18).Or(C("Age").GT(100))).Build()
fmt.Println(query.string())
Output:

SQL: SELECT `id` FROM `test_model` WHERE (`id`=?) OR (`age`>?);
Args: []interface {}{18, 100}

type Querier

type Querier[T any] struct {
	// contains filtered or unexported fields
}

Querier 查询器,代表最基本的查询

func RawQuery

func RawQuery[T any](sess session, sql string, args ...any) Querier[T]

RawQuery 创建一个 Querier 实例 泛型参数 T 是目标类型。 例如,如果查询 User 的数据,那么 T 就是 User

Example
orm := memoryDB()
q := RawQuery[any](orm, `SELECT * FROM user_tab WHERE id = ?;`, 1)
fmt.Printf(`
SQL: %s
Args: %v
`, q.q.SQL, q.q.Args)
Output:

SQL: SELECT * FROM user_tab WHERE id = ?;
Args: [1]

func (Querier[T]) Exec

func (q Querier[T]) Exec(ctx context.Context) Result

Exec 执行 SQL

Example
orm := memoryDB()
// 在 Exec 的时候,泛型参数可以是任意的
q := RawQuery[any](orm, `CREATE TABLE IF NOT EXISTS groups (
   group_id INTEGER PRIMARY KEY,
   name TEXT NOT NULL
)`)
res := q.Exec(context.Background())
if res.Err() == nil {
	fmt.Print("SUCCESS")
}
Output:

SUCCESS

func (Querier[T]) Get

func (q Querier[T]) Get(ctx context.Context) (*T, error)

Get 执行查询并且返回第一行数据 注意在不同的数据库里面,排序可能会不同 在没有查找到数据的情况下,会返回 ErrNoRows

func (Querier[T]) GetMulti

func (q Querier[T]) GetMulti(ctx context.Context) ([]*T, error)

type Query

type Query struct {
	SQL  string
	Args []any
}

Query 代表一个查询

type QueryBuilder

type QueryBuilder interface {
	Build() (*Query, error)
}

QueryBuilder is used to build a query

type RawExpr

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

RawExpr uses string as Expr

func Raw

func Raw(expr string, args ...interface{}) RawExpr

Raw just take expr as Expr

func (RawExpr) AsPredicate

func (r RawExpr) AsPredicate() Predicate

AsPredicate 将会返回一个 Predicate,RawExpr 将会作为这个 Predicate 的左边部分 eorm 将不会校验任何从 RawExpr 生成的 Predicate

Example
pred := Raw("`id`<?", 12).AsPredicate()
query, _ := NewSelector[TestModel](memoryDB()).From(&TestModel{}).Where(pred).Build()
fmt.Println(query.string())
Output:

SQL: SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model` WHERE `id`<?;
Args: []interface {}{12}

type Result

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

func (Result) Err

func (r Result) Err() error

func (Result) LastInsertId

func (r Result) LastInsertId() (int64, error)

func (Result) RowsAffected

func (r Result) RowsAffected() (int64, error)

type Selectable

type Selectable interface {
	// contains filtered or unexported methods
}

Selectable is a tag interface which represents SELECT XXX

type Selector

type Selector[T any] struct {
	// contains filtered or unexported fields
}

Selector represents a select query

func NewSelector

func NewSelector[T any](sess session) *Selector[T]

NewSelector 创建一个 Selector

func (*Selector[T]) Build

func (s *Selector[T]) Build() (*Query, error)

Build returns Select Query

func (*Selector[T]) Distinct

func (s *Selector[T]) Distinct() *Selector[T]

Distinct indicates using keyword DISTINCT

func (*Selector[T]) From

func (s *Selector[T]) From(table interface{}) *Selector[T]

From specifies the table which must be pointer of structure

func (*Selector[T]) Get

func (s *Selector[T]) Get(ctx context.Context) (*T, error)

Get 方法会执行查询,并且返回一条数据 注意,在不同的数据库情况下,第一条数据可能是按照不同的列来排序的 而且要注意,这个方法会强制设置 Limit 1 在没有查找到数据的情况下,会返回 ErrNoRows

func (*Selector[T]) GetMulti

func (s *Selector[T]) GetMulti(ctx context.Context) ([]*T, error)

func (*Selector[T]) GroupBy

func (s *Selector[T]) GroupBy(columns ...string) *Selector[T]

GroupBy means "GROUP BY"

func (*Selector[T]) Having

func (s *Selector[T]) Having(predicates ...Predicate) *Selector[T]

Having accepts predicates

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).Select(Columns("Id"), Columns("FirstName"), Avg("Age").As("avg_age")).From(&TestModel{}).GroupBy("FirstName").Having(C("avg_age").LT(20)).Build()
fmt.Printf("case1\n%s", query.string())
query, err := NewSelector[TestModel](db).Select(Columns("Id"), Columns("FirstName"), Avg("Age").As("avg_age")).From(&TestModel{}).GroupBy("FirstName").Having(C("Invalid").LT(20)).Build()
fmt.Printf("case2\n%s", err)
Output:

case1
SQL: SELECT `id`,`first_name`,AVG(`age`) AS `avg_age` FROM `test_model` GROUP BY `first_name` HAVING `avg_age`<?;
Args: []interface {}{20}
case2
eorm: 未知字段 Invalid

func (*Selector[T]) Limit

func (s *Selector[T]) Limit(limit int) *Selector[T]

Limit limits the size of result set

func (*Selector[T]) Offset

func (s *Selector[T]) Offset(offset int) *Selector[T]

Offset was used by "LIMIT"

func (*Selector[T]) OrderBy

func (s *Selector[T]) OrderBy(orderBys ...OrderBy) *Selector[T]

OrderBy means "ORDER BY"

Example
db := memoryDB()
query, _ := NewSelector[TestModel](db).From(&TestModel{}).OrderBy(ASC("Age")).Build()
fmt.Printf("case1\n%s", query.string())
query, _ = NewSelector[TestModel](db).From(&TestModel{}).OrderBy(ASC("Age", "Id")).Build()
fmt.Printf("case2\n%s", query.string())
query, _ = NewSelector[TestModel](db).From(&TestModel{}).OrderBy(ASC("Age"), ASC("Id")).Build()
fmt.Printf("case3\n%s", query.string())
query, _ = NewSelector[TestModel](db).From(&TestModel{}).OrderBy(ASC("Age"), DESC("Id")).Build()
fmt.Printf("case4\n%s", query.string())
Output:

case1
SQL: SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model` ORDER BY `age` ASC;
Args: []interface {}(nil)
case2
SQL: SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model` ORDER BY `age``id` ASC;
Args: []interface {}(nil)
case3
SQL: SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model` ORDER BY `age` ASC,`id` ASC;
Args: []interface {}(nil)
case4
SQL: SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model` ORDER BY `age` ASC,`id` DESC;
Args: []interface {}(nil)

func (*Selector[T]) Select

func (s *Selector[T]) Select(columns ...Selectable) *Selector[T]

Select 指定查询的列。 列可以是物理列,也可以是聚合函数,或者 RawExpr

Example
db := memoryDB()
tm := &TestModel{}
cases := []*Selector[TestModel]{
	// case0: all columns are included
	NewSelector[TestModel](db).From(tm),
	// case1: only query specific columns
	NewSelector[TestModel](db).Select(Columns("Id", "Age")).From(tm),
	// case2: using alias
	NewSelector[TestModel](db).Select(C("Id").As("my_id")).From(tm),
	// case3: using aggregation function and alias
	NewSelector[TestModel](db).Select(Avg("Age").As("avg_age")).From(tm),
	// case4: using raw expression
	NewSelector[TestModel](db).Select(Raw("COUNT(DISTINCT `age`) AS `age_cnt`")).From(tm),
}

for index, tc := range cases {
	query, _ := tc.Build()
	fmt.Printf("case%d:\n%s", index, query.string())
}
Output:

case0:
SQL: SELECT `id`,`first_name`,`age`,`last_name` FROM `test_model`;
Args: []interface {}(nil)
case1:
SQL: SELECT `id`,`age` FROM `test_model`;
Args: []interface {}(nil)
case2:
SQL: SELECT `id` AS `my_id` FROM `test_model`;
Args: []interface {}(nil)
case3:
SQL: SELECT AVG(`age`) AS `avg_age` FROM `test_model`;
Args: []interface {}(nil)
case4:
SQL: SELECT COUNT(DISTINCT `age`) AS `age_cnt` FROM `test_model`;
Args: []interface {}(nil)

func (*Selector[T]) Where

func (s *Selector[T]) Where(predicates ...Predicate) *Selector[T]

Where accepts predicates

type Tx

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

func (*Tx) Commit

func (t *Tx) Commit() error

func (*Tx) Rollback

func (t *Tx) Rollback() error

type Updater

type Updater[T any] struct {
	// contains filtered or unexported fields
}

Updater is the builder responsible for building UPDATE query

func NewUpdater

func NewUpdater[T any](sess session) *Updater[T]

NewUpdater 开始构建一个 UPDATE 查询

Example
db := memoryDB()
tm := &TestModel{
	Age: 18,
}
query, _ := NewUpdater[TestModel](db).Update(tm).Build()
fmt.Printf("SQL: %s", query.SQL)
Output:

SQL: UPDATE `test_model` SET `id`=?,`first_name`=?,`age`=?,`last_name`=?;

func (*Updater[T]) Build

func (u *Updater[T]) Build() (*Query, error)

Build returns UPDATE query

func (*Updater[T]) Exec

func (u *Updater[T]) Exec(ctx context.Context) Result

Exec sql

func (*Updater[T]) Set

func (u *Updater[T]) Set(assigns ...Assignable) *Updater[T]

Set represents SET clause

func (*Updater[T]) Update

func (u *Updater[T]) Update(val *T) *Updater[T]

func (*Updater[T]) Where

func (u *Updater[T]) Where(predicates ...Predicate) *Updater[T]

Where represents WHERE clause

Directories

Path Synopsis
internal
test
Package test 是用于辅助测试的包。
Package test 是用于辅助测试的包。

Jump to

Keyboard shortcuts

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