add sql execution support
This commit is contained in:
parent
74e0e3b175
commit
5870dbaab0
147
README.md
147
README.md
|
@ -7,12 +7,10 @@ xorm is an ORM for Go. It lets you map Go structs to tables in a database.
|
||||||
|
|
||||||
Right now, it interfaces with Mysql/SQLite. The goal however is to add support for PostgreSQL/DB2/MS ADODB/ODBC/Oracle in the future.
|
Right now, it interfaces with Mysql/SQLite. The goal however is to add support for PostgreSQL/DB2/MS ADODB/ODBC/Oracle in the future.
|
||||||
|
|
||||||
All in all, it's not entirely ready for advanced use yet, but it's getting there.
|
All in all, it's not entirely ready for product use yet, but it's getting there.
|
||||||
|
|
||||||
Drivers for Go's sql package which support database/sql includes:
|
Drivers for Go's sql package which support database/sql includes:
|
||||||
|
|
||||||
Mysql: [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv)
|
|
||||||
|
|
||||||
Mysql: [github.com/Go-SQL-Driver/MySQL](https://github.com/Go-SQL-Driver/MySQL)
|
Mysql: [github.com/Go-SQL-Driver/MySQL](https://github.com/Go-SQL-Driver/MySQL)
|
||||||
|
|
||||||
SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
|
SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
|
||||||
|
@ -55,19 +53,45 @@ then, insert an struct to table
|
||||||
or you want to update this struct
|
or you want to update this struct
|
||||||
|
|
||||||
|
|
||||||
user := User{Id:1, Name:"xlw"}
|
user := User{Name:"xlw"}
|
||||||
rows, err := engine.Update(&user)
|
rows, err := engine.Update(&user, &User{Id:1})
|
||||||
|
// rows, err := engine.Where("id = ?", 1).Update(&user)
|
||||||
|
|
||||||
|
|
||||||
3.Fetch a single object by user
|
3.Fetch a single object by user
|
||||||
|
|
||||||
|
|
||||||
var user = User{Id:27}
|
var user = User{Id:27}
|
||||||
engine.Get(&user)
|
err := engine.Get(&user)
|
||||||
|
|
||||||
var user = User{Name:"xlw"}
|
var user = User{Name:"xlw"}
|
||||||
engine.Get(&user)
|
err := engine.Get(&user)
|
||||||
|
|
||||||
|
4.Fetch multipe objects, use Find:
|
||||||
|
|
||||||
|
var allusers []Userinfo
|
||||||
|
err := engine.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
|
||||||
|
|
||||||
|
var tenusers []Userinfo
|
||||||
|
err := engine.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 if omit offset the default is 0
|
||||||
|
|
||||||
|
var everyone []Userinfo
|
||||||
|
err := engine.Find(&everyone)
|
||||||
|
|
||||||
|
5.Delete and Count:
|
||||||
|
|
||||||
|
err := engine.Delete(&User{Id:1})
|
||||||
|
|
||||||
|
total, err := engine.Count(&User{Name:"xlw"})
|
||||||
|
|
||||||
|
##Origin Use
|
||||||
|
Of course, the basic usage is also provided.
|
||||||
|
|
||||||
|
sql := "select * from userinfo"
|
||||||
|
results, err := engine.Query(sql)
|
||||||
|
|
||||||
|
sql = "update userinfo set username=? where id=?"
|
||||||
|
res, err := engine.Exec(sql, "xiaolun", 1)
|
||||||
|
|
||||||
##Deep Use
|
##Deep Use
|
||||||
for deep use, you should create a session, this func will create a connection to db
|
for deep use, you should create a session, this func will create a connection to db
|
||||||
|
@ -82,49 +106,120 @@ for deep use, you should create a session, this func will create a connection to
|
||||||
|
|
||||||
1.Fetch a single object by where
|
1.Fetch a single object by where
|
||||||
|
|
||||||
|
|
||||||
var user Userinfo
|
var user Userinfo
|
||||||
session.Where("id=?", 27).Get(&user)
|
session.Where("id=?", 27).Get(&user)
|
||||||
|
|
||||||
var user2 Userinfo
|
var user2 Userinfo
|
||||||
session.Where(3).Get(&user2) // this is shorthand for the version above
|
|
||||||
|
|
||||||
var user3 Userinfo
|
|
||||||
session.Where("name = ?", "john").Get(&user3) // more complex query
|
session.Where("name = ?", "john").Get(&user3) // more complex query
|
||||||
|
|
||||||
var user4 Userinfo
|
var user3 Userinfo
|
||||||
session.Where("name = ? and age < ?", "john", 88).Get(&user4) // even more complex
|
session.Where("name = ? and age < ?", "john", 88).Get(&user4) // even more complex
|
||||||
|
|
||||||
|
|
||||||
2.Fetch multiple objects
|
2.Fetch multiple objects
|
||||||
|
|
||||||
|
|
||||||
var allusers []Userinfo
|
var allusers []Userinfo
|
||||||
err := session.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
|
err := session.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
|
||||||
|
|
||||||
var tenusers []Userinfo
|
var tenusers []Userinfo
|
||||||
err := session.Where("id > ?", "3").Limit(10).Find(&tenusers) //Get id>3 limit 10 if omit offset the default is 0
|
err := session.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 if omit offset the default is 0
|
||||||
|
|
||||||
var everyone []Userinfo
|
var everyone []Userinfo
|
||||||
err := session.Find(&everyone)
|
err := session.Find(&everyone)
|
||||||
|
|
||||||
|
3.Transaction
|
||||||
|
|
||||||
|
// add Begin() before any action
|
||||||
|
session.Begin()
|
||||||
|
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
|
||||||
|
_, err = session.Insert(&user1)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user2 := Userinfo{Username: "yyy"}
|
||||||
|
_, err = session.Where("id = ?", 2).Update(&user2)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = session.Delete(&user2)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// add Commit() after all actions
|
||||||
|
err = session.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
4.Mixed Transaction
|
||||||
|
|
||||||
|
// add Begin() before any action
|
||||||
|
session.Begin()
|
||||||
|
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
|
||||||
|
_, err = session.Insert(&user1)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user2 := Userinfo{Username: "yyy"}
|
||||||
|
_, err = session.Where("id = ?", 2).Update(&user2)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = session.Exec("delete from userinfo where username = ?", user2.Username)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// add Commit() after all actions
|
||||||
|
err = session.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
##Mapping Rules
|
||||||
##***Mapping Rules***
|
|
||||||
1.Struct and struct's fields name should be Pascal style, and the table and column's name default is us
|
1.Struct and struct's fields name should be Pascal style, and the table and column's name default is us
|
||||||
for example:
|
|
||||||
|
For example:
|
||||||
The structs Name 'UserInfo' will turn into the table name 'user_info', the same as the keyname.
|
The structs Name 'UserInfo' will turn into the table name 'user_info', the same as the keyname.
|
||||||
If the keyname is 'UserName' will turn into the select colum 'user_name'
|
If the keyname is 'UserName' will turn into the select colum 'user_name'
|
||||||
|
|
||||||
2.You have two method to change the rule. One is implement your own Map interface according IMapper, you can find the interface in mapper.go and set it to engine.Mapper
|
2.You have two method to change the rule. One is implement your own Map interface according IMapper, you can find the interface in mapper.go and set it to engine.Mapper
|
||||||
|
|
||||||
another is use field tag, field tag support the below keywords:
|
another is use field tag, field tag support the below keywords:
|
||||||
* [name] column name
|
|
||||||
* pk the field is a primary key
|
<table>
|
||||||
* int(11)/varchar(50) column type
|
<tr>
|
||||||
* autoincr auto incrment
|
<td>name</td><td>column name</td>
|
||||||
* [not ]null if column can be null value
|
</tr>
|
||||||
* unique unique
|
<tr>
|
||||||
* \- this field is not map as a table column
|
<td>pk</td><td>the field is a primary key</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>int(11)/varchar(50)</td><td>column type</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>autoincr</td><td>auto incrment</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>[not ]null</td><td>if column can be null value</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>unique</td><td>unique</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>-</td><td>this field is not map as a table column</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
##FAQ
|
##FAQ
|
||||||
1.How the xorm tag use both with json?
|
1.How the xorm tag use both with json?
|
||||||
|
|
281
README_CN.md
281
README_CN.md
|
@ -1,127 +1,234 @@
|
||||||
xorm
|
# xorm
|
||||||
=====
|
===========
|
||||||
|
|
||||||
[English](README.md)
|
[English](README.md)
|
||||||
|
|
||||||
xorm 是一个Go语言的ORM(对象关系模型). It lets you map Go structs to tables in a database.
|
xorm是一个Go语言的ORM库. 通过它可以简化对数据库的操作。
|
||||||
|
|
||||||
|
目前仅支持Mysql和SQLite,当然我们的目标是支持PostgreSQL/DB2/MS ADODB/ODBC/Oracle等等。
|
||||||
|
|
||||||
Right now, it interfaces with Mysql/SQLite. The goal however is to add support for PostgreSQL/DB2/MS ADODB/ODBC/Oracle in the future.
|
但是,目前的版本还不可用于正式版本。
|
||||||
|
|
||||||
All in all, it's not entirely ready for advanced use yet, but it's getting there.
|
目前支持的Go数据库驱动如下:
|
||||||
|
|
||||||
Drivers for Go's sql package which support database/sql includes:
|
Mysql: [github.com/Go-SQL-Driver/MySQL](https://github.com/Go-SQL-Driver/MySQL)
|
||||||
|
|
||||||
Mysql:[github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv)
|
SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
|
||||||
|
|
||||||
Mysql:[github.com/Go-SQL-Driver/MySQL](https://github.com/Go-SQL-Driver/MySQL)
|
## 安装
|
||||||
|
|
||||||
|
go get github.com/lunny/xorm
|
||||||
|
|
||||||
SQLite:[github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
|
## 快速开始
|
||||||
|
|
||||||
### Installing xorm
|
1.创建数据库引擎 (例如: mysql)
|
||||||
go get github.com/lunny/xorm
|
|
||||||
|
|
||||||
### Quick Start
|
engine := xorm.Create("mysql://root:123@localhost/test")
|
||||||
|
|
||||||
1. Create an database engine (for example: mysql)
|
|
||||||
|
|
||||||
```go
|
2.定义你的Struct
|
||||||
engine := xorm.Create("mysql://root:123@localhost/test")
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Define your struct
|
|
||||||
|
|
||||||
```go
|
type User struct {
|
||||||
type User struct {
|
Id int
|
||||||
Id int
|
Name string
|
||||||
Name string
|
Age int `xorm:"-"`
|
||||||
Age int `xorm:"-"`
|
}
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
for Simple Task, just use engine's functions:
|
|
||||||
|
|
||||||
begin start, you should create a database and then we create the tables
|
对于简单的任务,可以只用engine一个对象就可以完成操作。
|
||||||
|
首先,需要创建一个数据库,然后使用以下语句创建一个Struct对应的表。
|
||||||
|
|
||||||
|
|
||||||
|
err := engine.CreateTables(&User{})
|
||||||
|
|
||||||
```go
|
|
||||||
err := engine.CreateTables(&User{})
|
|
||||||
```
|
|
||||||
|
|
||||||
then, insert an struct to table
|
然后,可以将一个结构体作为一条记录插入到表中。
|
||||||
|
|
||||||
```go
|
|
||||||
id, err := engine.Insert(&User{Name:"lunny"})
|
|
||||||
```
|
|
||||||
|
|
||||||
or you want to update this struct
|
id, err := engine.Insert(&User{Name:"lunny"})
|
||||||
|
|
||||||
```go
|
|
||||||
user := User{Id:1, Name:"xlw"}
|
|
||||||
rows, err := engine.Update(&user)
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Fetch a single object by user
|
或者执行更新操作:
|
||||||
```go
|
|
||||||
var user = User{Id:27}
|
|
||||||
engine.Get(&user)
|
|
||||||
|
|
||||||
var user = User{Name:"xlw"}
|
|
||||||
engine.Get(&user)
|
|
||||||
```
|
|
||||||
|
|
||||||
for deep use, you should create a session, this func will create a connection to db
|
user := User{Name:"xlw"}
|
||||||
|
rows, err := engine.Update(&user, &User{Id:1})
|
||||||
|
// rows, err := engine.Where("id = ?", 1).Update(&user)
|
||||||
|
|
||||||
```go
|
|
||||||
session, err := engine.MakeSession()
|
|
||||||
defer session.Close()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Fetch a single object by where
|
3.获取单个对象,可以用Get方法:
|
||||||
```go
|
|
||||||
var user Userinfo
|
|
||||||
session.Where("id=?", 27).Get(&user)
|
|
||||||
|
|
||||||
var user2 Userinfo
|
|
||||||
session.Where(3).Get(&user2) // this is shorthand for the version above
|
|
||||||
|
|
||||||
var user3 Userinfo
|
var user = User{Id:27}
|
||||||
session.Where("name = ?", "john").Get(&user3) // more complex query
|
err := engine.Get(&user)
|
||||||
|
|
||||||
var user4 Userinfo
|
var user = User{Name:"xlw"}
|
||||||
session.Where("name = ? and age < ?", "john", 88).Get(&user4) // even more complex
|
err := engine.Get(&user)
|
||||||
```
|
|
||||||
|
4.获取多个对象,可以用Find方法:
|
||||||
|
|
||||||
|
var allusers []Userinfo
|
||||||
|
err := engine.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
|
||||||
|
|
||||||
2. Fetch multiple objects
|
var tenusers []Userinfo
|
||||||
|
err := engine.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 if omit offset the default is 0
|
||||||
|
|
||||||
```go
|
var everyone []Userinfo
|
||||||
var allusers []Userinfo
|
err := engine.Find(&everyone)
|
||||||
err := session.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
|
|
||||||
|
5.另外还有Delete和Count方法:
|
||||||
|
|
||||||
|
err := engine.Delete(&User{Id:1})
|
||||||
|
|
||||||
|
total, err := engine.Count(&User{Name:"xlw"})
|
||||||
|
|
||||||
|
##Origin Use
|
||||||
|
当然,如果你想直接使用SQL语句进行操作,也是允许的。
|
||||||
|
|
||||||
|
sql := "select * from userinfo"
|
||||||
|
results, err := engine.Query(sql)
|
||||||
|
|
||||||
|
sql = "update userinfo set username=? where id=?"
|
||||||
|
res, err := engine.Exec(sql, "xiaolun", 1)
|
||||||
|
|
||||||
var tenusers []Userinfo
|
##Deep Use
|
||||||
err := session.Where("id > ?", "3").Limit(10).Find(&tenusers) //Get id>3 limit 10 if omit offset the default is 0
|
更高级的用法,我们必须要使用session对象,session对象在创建时会创建一个数据库连接。
|
||||||
|
|
||||||
var everyone []Userinfo
|
|
||||||
err := session.Find(&everyone)
|
|
||||||
```
|
|
||||||
|
|
||||||
###***About Map Rules***
|
session, err := engine.MakeSession()
|
||||||
1. Struct and struct's fields name should be Pascal style, and the table and column's name default is us
|
defer session.Close()
|
||||||
for example:
|
if err != nil {
|
||||||
The structs Name 'UserInfo' will turn into the table name 'user_info', the same as the keyname.
|
return
|
||||||
If the keyname is 'UserName' will turn into the select colum 'user_name'
|
}
|
||||||
|
|
||||||
2. You have two method to change the rule. One is implement your own Map interface according IMapper, you can find the interface in mapper.go and set it to engine.Mapper
|
|
||||||
|
|
||||||
another is use field tag, field tag support the below keywords:
|
1.session对象同样也可以查询
|
||||||
[name] column name
|
|
||||||
pk the field is a primary key
|
var user Userinfo
|
||||||
int(11)/varchar(50) column type
|
session.Where("id=?", 27).Get(&user)
|
||||||
autoincr auto incrment
|
|
||||||
[not ]null if column can be null value
|
var user2 Userinfo
|
||||||
unique unique
|
session.Where("name = ?", "john").Get(&user3) // more complex query
|
||||||
- this field is not map as a table column
|
|
||||||
|
var user3 Userinfo
|
||||||
|
session.Where("name = ? and age < ?", "john", 88).Get(&user4) // even more complex
|
||||||
|
|
||||||
|
|
||||||
|
2.获取多个对象
|
||||||
|
|
||||||
|
var allusers []Userinfo
|
||||||
|
err := session.Where("id > ?", "3").Limit(10,20).Find(&allusers) //Get id>3 limit 10 offset 20
|
||||||
|
|
||||||
|
var tenusers []Userinfo
|
||||||
|
err := session.Limit(10).Find(&tenusers, &Userinfo{Name:"xlw"}) //Get All Name="xlw" limit 10 if omit offset the default is 0
|
||||||
|
|
||||||
|
var everyone []Userinfo
|
||||||
|
err := session.Find(&everyone)
|
||||||
|
|
||||||
|
3.事务处理
|
||||||
|
|
||||||
|
// add Begin() before any action
|
||||||
|
session.Begin()
|
||||||
|
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
|
||||||
|
_, err = session.Insert(&user1)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user2 := Userinfo{Username: "yyy"}
|
||||||
|
_, err = session.Where("id = ?", 2).Update(&user2)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = session.Delete(&user2)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// add Commit() after all actions
|
||||||
|
err = session.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
4.混合型事务,这个事务中,既有直接的SQL语句,又有其它方法:
|
||||||
|
|
||||||
|
// add Begin() before any action
|
||||||
|
session.Begin()
|
||||||
|
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
|
||||||
|
_, err = session.Insert(&user1)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user2 := Userinfo{Username: "yyy"}
|
||||||
|
_, err = session.Where("id = ?", 2).Update(&user2)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = session.Exec("delete from userinfo where username = ?", user2.Username)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// add Commit() after all actions
|
||||||
|
err = session.Commit()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
##Mapping Rules
|
||||||
|
1.Struct 和 Struct 的field名字应该为Pascal式命名,默认的映射规则将转换成用下划线连接的命名规则,这个映射是自动进行的,当然,你可以通过修改Engine或者Session的成员IMapper来改变它。
|
||||||
|
|
||||||
|
例如:
|
||||||
|
|
||||||
|
结构体的名字UserInfo将会自动对应数据库中的名为user_info的表。
|
||||||
|
UserInfo中的成员UserName将会自动对应名为user_name的字段。
|
||||||
|
|
||||||
|
2.当然你也可以改变这个规则,这有两种方法。一是实现你自己的IMapper,你可以在mapper.go中查看到这个借口。然后设置到 engine.Mapper,这将影响所有的Session,或者你可以设置到某一个session,那么只会影响到这个session对应的操作。
|
||||||
|
|
||||||
|
另外一种方法就通过Field Tag来进行改变,关于Field Tag请参考Go的语言文档,如下列出了Tag中可用的关键字及其对应的意义:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>name</td><td>当前field对应的字段的名称,可选</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>pk</td><td>是否是Primary Key</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>int(11)/varchar(50)</td><td>字段类型</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>autoincr</td><td>是否是自增</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>[not ]null</td><td>是否可以为空</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>unique</td><td>是否是唯一</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>-</td><td>这个Field将不进行字段映射</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
##FAQ
|
||||||
|
1.xorm的tag和json的tag如何同时起作用?
|
||||||
|
|
||||||
|
使用空格分开
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
User string `json:"user" orm:"user_id"`
|
||||||
|
}
|
||||||
|
|
||||||
## LICENSE
|
## LICENSE
|
||||||
|
|
||||||
|
|
44
engine.go
44
engine.go
|
@ -341,6 +341,24 @@ func (e *Engine) CreateAll() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (engine *Engine) Exec(sql string, args ...interface{}) (sql.Result, error) {
|
||||||
|
session, err := engine.MakeSession()
|
||||||
|
defer session.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return session.Exec(sql, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (engine *Engine) Query(sql string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
|
||||||
|
session, err := engine.MakeSession()
|
||||||
|
defer session.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return session.Query(sql, paramStr...)
|
||||||
|
}
|
||||||
|
|
||||||
func (engine *Engine) Insert(beans ...interface{}) (int64, error) {
|
func (engine *Engine) Insert(beans ...interface{}) (int64, error) {
|
||||||
session, err := engine.MakeSession()
|
session, err := engine.MakeSession()
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
@ -348,21 +366,19 @@ func (engine *Engine) Insert(beans ...interface{}) (int64, error) {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
defer engine.Statement.Init()
|
defer engine.Statement.Init()
|
||||||
engine.Statement.Session = &session
|
session.Statement = engine.Statement
|
||||||
session.SetStatement(&engine.Statement)
|
|
||||||
return session.Insert(beans...)
|
return session.Insert(beans...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (engine *Engine) Update(bean interface{}) (int64, error) {
|
func (engine *Engine) Update(bean interface{}, condiBeans ...interface{}) (int64, error) {
|
||||||
session, err := engine.MakeSession()
|
session, err := engine.MakeSession()
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
defer engine.Statement.Init()
|
defer engine.Statement.Init()
|
||||||
engine.Statement.Session = &session
|
session.Statement = engine.Statement
|
||||||
session.SetStatement(&engine.Statement)
|
return session.Update(bean, condiBeans...)
|
||||||
return session.Update(bean)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (engine *Engine) Delete(bean interface{}) (int64, error) {
|
func (engine *Engine) Delete(bean interface{}) (int64, error) {
|
||||||
|
@ -372,8 +388,7 @@ func (engine *Engine) Delete(bean interface{}) (int64, error) {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
defer engine.Statement.Init()
|
defer engine.Statement.Init()
|
||||||
engine.Statement.Session = &session
|
session.Statement = engine.Statement
|
||||||
session.SetStatement(&engine.Statement)
|
|
||||||
return session.Delete(bean)
|
return session.Delete(bean)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,21 +399,19 @@ func (engine *Engine) Get(bean interface{}) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer engine.Statement.Init()
|
defer engine.Statement.Init()
|
||||||
engine.Statement.Session = &session
|
session.Statement = engine.Statement
|
||||||
session.SetStatement(&engine.Statement)
|
|
||||||
return session.Get(bean)
|
return session.Get(bean)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (engine *Engine) Find(beans interface{}) error {
|
func (engine *Engine) Find(beans interface{}, condiBeans ...interface{}) error {
|
||||||
session, err := engine.MakeSession()
|
session, err := engine.MakeSession()
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer engine.Statement.Init()
|
defer engine.Statement.Init()
|
||||||
engine.Statement.Session = &session
|
session.Statement = engine.Statement
|
||||||
session.SetStatement(&engine.Statement)
|
return session.Find(beans, condiBeans...)
|
||||||
return session.Find(beans)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (engine *Engine) Count(bean interface{}) (int64, error) {
|
func (engine *Engine) Count(bean interface{}) (int64, error) {
|
||||||
|
@ -408,7 +421,6 @@ func (engine *Engine) Count(bean interface{}) (int64, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer engine.Statement.Init()
|
defer engine.Statement.Init()
|
||||||
engine.Statement.Session = &session
|
session.Statement = engine.Statement
|
||||||
session.SetStatement(&engine.Statement)
|
|
||||||
return session.Count(bean)
|
return session.Count(bean)
|
||||||
}
|
}
|
||||||
|
|
252
session.go
252
session.go
|
@ -35,97 +35,75 @@ func Type2StructName(v reflect.Type) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Session struct {
|
type Session struct {
|
||||||
Db *sql.DB
|
Db *sql.DB
|
||||||
Engine *Engine
|
Engine *Engine
|
||||||
Tx *sql.Tx
|
Tx *sql.Tx
|
||||||
Statements []Statement
|
Statement Statement
|
||||||
Mapper IMapper
|
Mapper IMapper
|
||||||
IsAutoCommit bool
|
IsAutoCommit bool
|
||||||
IsAutoRollback bool
|
|
||||||
CurStatementIdx int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Init() {
|
func (session *Session) Init() {
|
||||||
session.Statements = make([]Statement, 0)
|
session.Statement = Statement{}
|
||||||
session.CurStatementIdx = -1
|
|
||||||
session.IsAutoCommit = true
|
session.IsAutoCommit = true
|
||||||
session.IsAutoRollback = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Close() {
|
func (session *Session) Close() {
|
||||||
rollbackfunc := func() {
|
|
||||||
if session.IsAutoRollback {
|
|
||||||
session.Rollback()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer rollbackfunc()
|
|
||||||
defer session.Db.Close()
|
defer session.Db.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) CurrentStatement() *Statement {
|
|
||||||
if session.CurStatementIdx > -1 {
|
|
||||||
return &session.Statements[session.CurStatementIdx]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) AutoStatement() *Statement {
|
|
||||||
if session.CurStatementIdx == -1 {
|
|
||||||
session.newStatement()
|
|
||||||
}
|
|
||||||
return session.CurrentStatement()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) Where(querystring string, args ...interface{}) *Session {
|
func (session *Session) Where(querystring string, args ...interface{}) *Session {
|
||||||
statement := session.AutoStatement()
|
session.Statement.Where(querystring, args...)
|
||||||
statement.Where(querystring, args...)
|
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Limit(limit int, start ...int) *Session {
|
func (session *Session) Limit(limit int, start ...int) *Session {
|
||||||
statement := session.AutoStatement()
|
session.Statement.Limit(limit, start...)
|
||||||
statement.Limit(limit, start...)
|
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) OrderBy(order string) *Session {
|
func (session *Session) OrderBy(order string) *Session {
|
||||||
statement := session.AutoStatement()
|
session.Statement.OrderBy(order)
|
||||||
statement.OrderBy(order)
|
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
//The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
|
//The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
|
||||||
func (session *Session) Join(join_operator, tablename, condition string) *Session {
|
func (session *Session) Join(join_operator, tablename, condition string) *Session {
|
||||||
statement := session.AutoStatement()
|
session.Statement.Join(join_operator, tablename, condition)
|
||||||
statement.Join(join_operator, tablename, condition)
|
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) GroupBy(keys string) *Session {
|
func (session *Session) GroupBy(keys string) *Session {
|
||||||
statement := session.AutoStatement()
|
session.Statement.GroupBy(keys)
|
||||||
statement.GroupBy(keys)
|
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Having(conditions string) *Session {
|
func (session *Session) Having(conditions string) *Session {
|
||||||
statement := session.AutoStatement()
|
session.Statement.Having(conditions)
|
||||||
statement.Having(conditions)
|
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Begin() error {
|
func (session *Session) Begin() error {
|
||||||
session.IsAutoCommit = false
|
session.IsAutoCommit = false
|
||||||
session.IsAutoRollback = true
|
|
||||||
tx, err := session.Db.Begin()
|
tx, err := session.Db.Begin()
|
||||||
session.Tx = tx
|
session.Tx = tx
|
||||||
|
if session.Engine.ShowSQL {
|
||||||
|
fmt.Println("BEGIN TRANSACTION")
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Rollback() error {
|
func (session *Session) Rollback() error {
|
||||||
|
if session.Engine.ShowSQL {
|
||||||
|
fmt.Println("ROLL BACK")
|
||||||
|
}
|
||||||
return session.Tx.Rollback()
|
return session.Tx.Rollback()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Commit() error {
|
func (session *Session) Commit() error {
|
||||||
|
if session.Engine.ShowSQL {
|
||||||
|
fmt.Println("COMMIT")
|
||||||
|
}
|
||||||
return session.Tx.Commit()
|
return session.Tx.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,27 +111,10 @@ func (session *Session) TableName(bean interface{}) string {
|
||||||
return session.Mapper.Obj2Table(StructName(bean))
|
return session.Mapper.Obj2Table(StructName(bean))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) SetStatement(statement *Statement) {
|
func (session *Session) Bean2Table(bean interface{}) *Table {
|
||||||
if session.CurStatementIdx == len(session.Statements)-1 {
|
tablName := session.TableName(bean)
|
||||||
session.Statements = append(session.Statements, *statement)
|
table := session.Engine.Tables[tablName]
|
||||||
} else {
|
return &table
|
||||||
session.Statements[session.CurStatementIdx+1] = *statement
|
|
||||||
}
|
|
||||||
session.CurStatementIdx = session.CurStatementIdx + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) newStatement() {
|
|
||||||
if session.CurStatementIdx == len(session.Statements)-1 {
|
|
||||||
state := Statement{Session: session}
|
|
||||||
state.Init()
|
|
||||||
session.Statements = append(session.Statements, state)
|
|
||||||
}
|
|
||||||
session.CurStatementIdx = session.CurStatementIdx + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) clearStatment() {
|
|
||||||
session.Statements[session.CurStatementIdx].Init()
|
|
||||||
session.CurStatementIdx = session.CurStatementIdx - 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]byte) error {
|
func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]byte) error {
|
||||||
|
@ -162,8 +123,7 @@ func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]b
|
||||||
return errors.New("expected a pointer to a struct")
|
return errors.New("expected a pointer to a struct")
|
||||||
}
|
}
|
||||||
|
|
||||||
tablName := session.TableName(obj)
|
table := session.Bean2Table(obj)
|
||||||
table := session.Engine.Tables[tablName]
|
|
||||||
|
|
||||||
for key, data := range objMap {
|
for key, data := range objMap {
|
||||||
structField := dataStruct.FieldByName(table.Columns[key].FieldName)
|
structField := dataStruct.FieldByName(table.Columns[key].FieldName)
|
||||||
|
@ -231,8 +191,8 @@ func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]b
|
||||||
}
|
}
|
||||||
|
|
||||||
//Execute sql
|
//Execute sql
|
||||||
func (session *Session) Exec(finalQueryString string, args ...interface{}) (sql.Result, error) {
|
func (session *Session) innerExec(sql string, args ...interface{}) (sql.Result, error) {
|
||||||
rs, err := session.Db.Prepare(finalQueryString)
|
rs, err := session.Db.Prepare(sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -245,18 +205,30 @@ func (session *Session) Exec(finalQueryString string, args ...interface{}) (sql.
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Get(bean interface{}) error {
|
func (session *Session) Exec(sql string, args ...interface{}) (sql.Result, error) {
|
||||||
statement := session.AutoStatement()
|
if session.Engine.ShowSQL {
|
||||||
statement.Limit(1)
|
fmt.Println(sql)
|
||||||
tableName := session.TableName(bean)
|
}
|
||||||
table := session.Engine.Tables[tableName]
|
if session.IsAutoCommit {
|
||||||
statement.Table = &table
|
return session.innerExec(sql, args...)
|
||||||
|
}
|
||||||
|
return session.Tx.Exec(sql, args...)
|
||||||
|
}
|
||||||
|
|
||||||
colNames, args := session.BuildConditions(&table, bean)
|
func (session *Session) Get(bean interface{}) error {
|
||||||
|
statement := session.Statement
|
||||||
|
defer session.Statement.Init()
|
||||||
|
statement.Limit(1)
|
||||||
|
table := session.Bean2Table(bean)
|
||||||
|
statement.Table = table
|
||||||
|
|
||||||
|
colNames, args := session.BuildConditions(table, bean)
|
||||||
statement.ColumnStr = strings.Join(colNames, " and ")
|
statement.ColumnStr = strings.Join(colNames, " and ")
|
||||||
statement.BeanArgs = args
|
statement.BeanArgs = args
|
||||||
|
|
||||||
resultsSlice, err := session.FindMap(statement)
|
sql := statement.generateSql()
|
||||||
|
resultsSlice, err := session.Query(sql, append(statement.Params, statement.BeanArgs...)...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -275,16 +247,16 @@ func (session *Session) Get(bean interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Count(bean interface{}) (int64, error) {
|
func (session *Session) Count(bean interface{}) (int64, error) {
|
||||||
statement := session.AutoStatement()
|
statement := session.Statement
|
||||||
tableName := session.TableName(bean)
|
defer session.Statement.Init()
|
||||||
table := session.Engine.Tables[tableName]
|
table := session.Bean2Table(bean)
|
||||||
statement.Table = &table
|
statement.Table = table
|
||||||
|
|
||||||
colNames, args := session.BuildConditions(&table, bean)
|
colNames, args := session.BuildConditions(table, bean)
|
||||||
statement.ColumnStr = strings.Join(colNames, " and ")
|
statement.ColumnStr = strings.Join(colNames, " and ")
|
||||||
statement.BeanArgs = args
|
statement.BeanArgs = args
|
||||||
|
|
||||||
resultsSlice, err := session.SQL2Map(statement.genCountSql(), append(statement.Params, statement.BeanArgs...))
|
resultsSlice, err := session.Query(statement.genCountSql(), append(statement.Params, statement.BeanArgs...)...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -298,9 +270,9 @@ func (session *Session) Count(bean interface{}) (int64, error) {
|
||||||
return int64(total), err
|
return int64(total), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Find(rowsSlicePtr interface{}) error {
|
func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{}) error {
|
||||||
statement := session.AutoStatement()
|
statement := session.Statement
|
||||||
|
defer session.Statement.Init()
|
||||||
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
|
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
|
||||||
if sliceValue.Kind() != reflect.Slice {
|
if sliceValue.Kind() != reflect.Slice {
|
||||||
return errors.New("needs a pointer to a slice")
|
return errors.New("needs a pointer to a slice")
|
||||||
|
@ -312,7 +284,15 @@ func (session *Session) Find(rowsSlicePtr interface{}) error {
|
||||||
table := session.Engine.Tables[tableName]
|
table := session.Engine.Tables[tableName]
|
||||||
statement.Table = &table
|
statement.Table = &table
|
||||||
|
|
||||||
resultsSlice, err := session.FindMap(statement)
|
if len(condiBean) > 0 {
|
||||||
|
colNames, args := session.BuildConditions(&table, condiBean[0])
|
||||||
|
statement.ColumnStr = strings.Join(colNames, " and ")
|
||||||
|
statement.BeanArgs = args
|
||||||
|
}
|
||||||
|
|
||||||
|
sql := statement.generateSql()
|
||||||
|
resultsSlice, err := session.Query(sql, append(statement.Params, statement.BeanArgs...)...)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -328,7 +308,7 @@ func (session *Session) Find(rowsSlicePtr interface{}) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) SQL2Map(sqls string, paramStr []interface{}) (resultsSlice []map[string][]byte, err error) {
|
func (session *Session) Query(sqls string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
|
||||||
if session.Engine.ShowSQL {
|
if session.Engine.ShowSQL {
|
||||||
fmt.Println(sqls)
|
fmt.Println(sqls)
|
||||||
}
|
}
|
||||||
|
@ -397,11 +377,6 @@ func (session *Session) SQL2Map(sqls string, paramStr []interface{}) (resultsSli
|
||||||
return resultsSlice, nil
|
return resultsSlice, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) FindMap(statement *Statement) (resultsSlice []map[string][]byte, err error) {
|
|
||||||
sqls := statement.generateSql()
|
|
||||||
return session.SQL2Map(sqls, append(statement.Params, statement.BeanArgs...))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (session *Session) Insert(beans ...interface{}) (int64, error) {
|
func (session *Session) Insert(beans ...interface{}) (int64, error) {
|
||||||
var lastId int64 = -1
|
var lastId int64 = -1
|
||||||
for _, bean := range beans {
|
for _, bean := range beans {
|
||||||
|
@ -414,8 +389,7 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) InsertOne(bean interface{}) (int64, error) {
|
func (session *Session) InsertOne(bean interface{}) (int64, error) {
|
||||||
tableName := session.TableName(bean)
|
table := session.Bean2Table(bean)
|
||||||
table := session.Engine.Tables[tableName]
|
|
||||||
|
|
||||||
colNames := make([]string, 0)
|
colNames := make([]string, 0)
|
||||||
colPlaces := make([]string, 0)
|
colPlaces := make([]string, 0)
|
||||||
|
@ -423,10 +397,8 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
|
||||||
for _, col := range table.Columns {
|
for _, col := range table.Columns {
|
||||||
fieldValue := reflect.Indirect(reflect.ValueOf(bean)).FieldByName(col.FieldName)
|
fieldValue := reflect.Indirect(reflect.ValueOf(bean)).FieldByName(col.FieldName)
|
||||||
val := fieldValue.Interface()
|
val := fieldValue.Interface()
|
||||||
if col.IsAutoIncrement {
|
if col.IsAutoIncrement && fieldValue.Int() == 0 {
|
||||||
if fieldValue.Int() == 0 {
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
args = append(args, val)
|
args = append(args, val)
|
||||||
colNames = append(colNames, col.Name)
|
colNames = append(colNames, col.Name)
|
||||||
|
@ -435,23 +407,12 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
|
||||||
|
|
||||||
statement := fmt.Sprintf("INSERT INTO %v%v%v (%v) VALUES (%v)",
|
statement := fmt.Sprintf("INSERT INTO %v%v%v (%v) VALUES (%v)",
|
||||||
session.Engine.QuoteIdentifier,
|
session.Engine.QuoteIdentifier,
|
||||||
tableName,
|
table.Name,
|
||||||
session.Engine.QuoteIdentifier,
|
session.Engine.QuoteIdentifier,
|
||||||
strings.Join(colNames, ", "),
|
strings.Join(colNames, ", "),
|
||||||
strings.Join(colPlaces, ", "))
|
strings.Join(colPlaces, ", "))
|
||||||
|
|
||||||
if session.Engine.ShowSQL {
|
res, err := session.Exec(statement, args...)
|
||||||
fmt.Println(statement)
|
|
||||||
}
|
|
||||||
|
|
||||||
var res sql.Result
|
|
||||||
var err error
|
|
||||||
|
|
||||||
if session.IsAutoCommit {
|
|
||||||
res, err = session.Exec(statement, args...)
|
|
||||||
} else {
|
|
||||||
res, err = session.Tx.Exec(statement, args...)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
@ -461,6 +422,7 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return id, nil
|
return id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,46 +459,42 @@ func (session *Session) BuildConditions(table *Table, bean interface{}) ([]strin
|
||||||
return colNames, args
|
return colNames, args
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Update(bean interface{}) (int64, error) {
|
func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int64, error) {
|
||||||
tableName := session.TableName(bean)
|
table := session.Bean2Table(bean)
|
||||||
table := session.Engine.Tables[tableName]
|
colNames, args := session.BuildConditions(table, bean)
|
||||||
colNames, args := session.BuildConditions(&table, bean)
|
var condiColNames []string
|
||||||
|
var condiArgs []interface{}
|
||||||
|
|
||||||
|
if len(condiBean) > 0 {
|
||||||
|
condiColNames, condiArgs = session.BuildConditions(table, condiBean[0])
|
||||||
|
}
|
||||||
|
|
||||||
var condition = ""
|
var condition = ""
|
||||||
st := session.AutoStatement()
|
st := session.Statement
|
||||||
defer session.clearStatment()
|
defer session.Statement.Init()
|
||||||
if st.WhereStr != "" {
|
if st.WhereStr != "" {
|
||||||
condition = fmt.Sprintf("WHERE %v", st.WhereStr)
|
condition = fmt.Sprintf("WHERE %v", st.WhereStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if condition == "" {
|
if condition == "" {
|
||||||
fieldValue := reflect.Indirect(reflect.ValueOf(bean)).FieldByName(table.PKColumn().FieldName)
|
if len(condiColNames) > 0 {
|
||||||
if fieldValue.Int() != 0 {
|
condition = fmt.Sprintf("WHERE %v ", strings.Join(condiColNames, " and "))
|
||||||
condition = fmt.Sprintf("WHERE %v = ?", table.PKColumn().Name)
|
}
|
||||||
args = append(args, fieldValue.Interface())
|
} else {
|
||||||
|
if len(condiColNames) > 0 {
|
||||||
|
condition = fmt.Sprintf("%v and %v", condition, strings.Join(condiColNames, " and "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
statement := fmt.Sprintf("UPDATE %v%v%v SET %v %v",
|
statement := fmt.Sprintf("UPDATE %v%v%v SET %v %v",
|
||||||
session.Engine.QuoteIdentifier,
|
session.Engine.QuoteIdentifier,
|
||||||
tableName,
|
table.Name,
|
||||||
session.Engine.QuoteIdentifier,
|
session.Engine.QuoteIdentifier,
|
||||||
strings.Join(colNames, ", "),
|
strings.Join(colNames, ", "),
|
||||||
condition)
|
condition)
|
||||||
|
|
||||||
if session.Engine.ShowSQL {
|
eargs := append(append(args, st.Params...), condiArgs...)
|
||||||
fmt.Println(statement)
|
res, err := session.Exec(statement, eargs...)
|
||||||
}
|
|
||||||
|
|
||||||
var res sql.Result
|
|
||||||
var err error
|
|
||||||
if session.IsAutoCommit {
|
|
||||||
fmt.Println("session.Exec")
|
|
||||||
res, err = session.Exec(statement, append(args, st.Params...)...)
|
|
||||||
} else {
|
|
||||||
fmt.Println("tx.Exec")
|
|
||||||
res, err = session.Tx.Exec(statement, append(args, st.Params...)...)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
@ -550,13 +508,12 @@ func (session *Session) Update(bean interface{}) (int64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (session *Session) Delete(bean interface{}) (int64, error) {
|
func (session *Session) Delete(bean interface{}) (int64, error) {
|
||||||
tableName := session.TableName(bean)
|
table := session.Bean2Table(bean)
|
||||||
table := session.Engine.Tables[tableName]
|
colNames, args := session.BuildConditions(table, bean)
|
||||||
colNames, args := session.BuildConditions(&table, bean)
|
|
||||||
|
|
||||||
var condition = ""
|
var condition = ""
|
||||||
st := session.AutoStatement()
|
st := session.Statement
|
||||||
defer session.clearStatment()
|
defer session.Statement.Init()
|
||||||
if st.WhereStr != "" {
|
if st.WhereStr != "" {
|
||||||
condition = fmt.Sprintf("WHERE %v", st.WhereStr)
|
condition = fmt.Sprintf("WHERE %v", st.WhereStr)
|
||||||
if len(colNames) > 0 {
|
if len(colNames) > 0 {
|
||||||
|
@ -569,21 +526,12 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
|
||||||
|
|
||||||
statement := fmt.Sprintf("DELETE FROM %v%v%v %v",
|
statement := fmt.Sprintf("DELETE FROM %v%v%v %v",
|
||||||
session.Engine.QuoteIdentifier,
|
session.Engine.QuoteIdentifier,
|
||||||
tableName,
|
table.Name,
|
||||||
session.Engine.QuoteIdentifier,
|
session.Engine.QuoteIdentifier,
|
||||||
condition)
|
condition)
|
||||||
|
|
||||||
if session.Engine.ShowSQL {
|
res, err := session.Exec(statement, append(st.Params, args...)...)
|
||||||
fmt.Println(statement)
|
|
||||||
}
|
|
||||||
|
|
||||||
var res sql.Result
|
|
||||||
var err error
|
|
||||||
if session.IsAutoCommit {
|
|
||||||
res, err = session.Exec(statement, append(st.Params, args...)...)
|
|
||||||
} else {
|
|
||||||
res, err = session.Tx.Exec(statement, append(st.Params, args...)...)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return -1, err
|
return -1, err
|
||||||
}
|
}
|
||||||
|
|
31
statement.go
31
statement.go
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
type Statement struct {
|
type Statement struct {
|
||||||
Table *Table
|
Table *Table
|
||||||
Session *Session
|
Engine *Engine
|
||||||
Start int
|
Start int
|
||||||
LimitN int
|
LimitN int
|
||||||
WhereStr string
|
WhereStr string
|
||||||
|
@ -21,7 +21,6 @@ type Statement struct {
|
||||||
|
|
||||||
func (statement *Statement) Init() {
|
func (statement *Statement) Init() {
|
||||||
statement.Table = nil
|
statement.Table = nil
|
||||||
statement.Session = nil
|
|
||||||
statement.Start = 0
|
statement.Start = 0
|
||||||
statement.LimitN = 0
|
statement.LimitN = 0
|
||||||
statement.WhereStr = ""
|
statement.WhereStr = ""
|
||||||
|
@ -76,13 +75,8 @@ func (statement Statement) genCountSql() string {
|
||||||
return statement.genSelectSql("count(*) as total")
|
return statement.genSelectSql("count(*) as total")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (statement Statement) genExecSql() string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (statement Statement) genSelectSql(columnStr string) (a string) {
|
func (statement Statement) genSelectSql(columnStr string) (a string) {
|
||||||
session := statement.Session
|
if statement.Engine.Protocol == "mssql" {
|
||||||
if session.Engine.Protocol == "mssql" {
|
|
||||||
if statement.Start > 0 {
|
if statement.Start > 0 {
|
||||||
a = fmt.Sprintf("select ROW_NUMBER() OVER(order by %v )as rownum,%v from %v",
|
a = fmt.Sprintf("select ROW_NUMBER() OVER(order by %v )as rownum,%v from %v",
|
||||||
statement.Table.PKColumn().Name,
|
statement.Table.PKColumn().Name,
|
||||||
|
@ -171,24 +165,3 @@ func (statement Statement) genSelectSql(columnStr string) (a string) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*func (statement *Statement) genInsertSQL() string {
|
|
||||||
table = statement.Table
|
|
||||||
colNames := make([]string, len(table.Columns))
|
|
||||||
for idx, col := range table.Columns {
|
|
||||||
if col.Name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
colNames[idx] = col.Name
|
|
||||||
}
|
|
||||||
return strings.Join(colNames, ", ")
|
|
||||||
|
|
||||||
colNames := make([]string, len(table.Columns))
|
|
||||||
for idx, col := range table.Columns {
|
|
||||||
if col.Name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
colNames[idx] = "?"
|
|
||||||
}
|
|
||||||
strings.Join(colNames, ", ")
|
|
||||||
}*/
|
|
||||||
|
|
2
table.go
2
table.go
|
@ -72,7 +72,7 @@ type Table struct {
|
||||||
func (table *Table) ColumnStr() string {
|
func (table *Table) ColumnStr() string {
|
||||||
colNames := make([]string, 0)
|
colNames := make([]string, 0)
|
||||||
for _, col := range table.Columns {
|
for _, col := range table.Columns {
|
||||||
colNames = append(colNames, col.Name)
|
colNames = append(colNames, table.Name+"."+col.Name)
|
||||||
}
|
}
|
||||||
return strings.Join(colNames, ", ")
|
return strings.Join(colNames, ", ")
|
||||||
}
|
}
|
||||||
|
|
1
xorm.go
1
xorm.go
|
@ -12,6 +12,7 @@ func Create(schema string) Engine {
|
||||||
engine := Engine{}
|
engine := Engine{}
|
||||||
engine.Mapper = SnakeMapper{}
|
engine.Mapper = SnakeMapper{}
|
||||||
engine.Tables = make(map[string]Table)
|
engine.Tables = make(map[string]Table)
|
||||||
|
engine.Statement.Engine = &engine
|
||||||
l := strings.Split(schema, "://")
|
l := strings.Split(schema, "://")
|
||||||
if len(l) == 2 {
|
if len(l) == 2 {
|
||||||
engine.Protocol = l[0]
|
engine.Protocol = l[0]
|
||||||
|
|
136
xorm_test.go
136
xorm_test.go
|
@ -33,6 +33,12 @@ type Userinfo struct {
|
||||||
Created time.Time
|
Created time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Userdetail struct {
|
||||||
|
Uid int `xorm:"id pk not null"`
|
||||||
|
Intro string
|
||||||
|
Profile string
|
||||||
|
}
|
||||||
|
|
||||||
var engine xorm.Engine
|
var engine xorm.Engine
|
||||||
|
|
||||||
func directCreateTable(t *testing.T) {
|
func directCreateTable(t *testing.T) {
|
||||||
|
@ -48,7 +54,7 @@ func mapper(t *testing.T) {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = engine.Map(&Userinfo{})
|
err = engine.Map(&Userinfo{}, &Userdetail{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -72,6 +78,24 @@ func insert(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func query(t *testing.T) {
|
||||||
|
sql := "select * from userinfo"
|
||||||
|
results, err := engine.Query(sql)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
fmt.Println(results)
|
||||||
|
}
|
||||||
|
|
||||||
|
func exec(t *testing.T) {
|
||||||
|
sql := "update userinfo set username=? where id=?"
|
||||||
|
res, err := engine.Exec(sql, "xiaolun", 1)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
fmt.Println(res)
|
||||||
|
}
|
||||||
|
|
||||||
func insertAutoIncr(t *testing.T) {
|
func insertAutoIncr(t *testing.T) {
|
||||||
// auto increment insert
|
// auto increment insert
|
||||||
user := Userinfo{Username: "xiaolunwen", Departname: "dev", Alias: "lunny", Created: time.Now()}
|
user := Userinfo{Username: "xiaolunwen", Departname: "dev", Alias: "lunny", Created: time.Now()}
|
||||||
|
@ -90,10 +114,26 @@ func insertMulti(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func insertTwoTable(t *testing.T) {
|
||||||
|
userinfo := Userinfo{Username: "xlw3", Departname: "dev", Alias: "lunny4", Created: time.Now()}
|
||||||
|
uid, err := engine.Insert(&userinfo)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
userdetail := Userdetail{Uid: int(uid), Intro: "I'm a very beautiful women.", Profile: "sfsaf"}
|
||||||
|
_, err = engine.Insert(&userdetail)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func update(t *testing.T) {
|
func update(t *testing.T) {
|
||||||
// update by id
|
// update by id
|
||||||
user := Userinfo{Uid: 1, Username: "xxx"}
|
user := Userinfo{Username: "xxx"}
|
||||||
_, err := engine.Update(&user)
|
condiUser := Userinfo{Uid: 1}
|
||||||
|
_, err := engine.Update(&user, &condiUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
|
@ -163,6 +203,23 @@ func order(t *testing.T) {
|
||||||
fmt.Println(users)
|
fmt.Println(users)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func join(t *testing.T) {
|
||||||
|
users := make([]Userinfo, 0)
|
||||||
|
err := engine.Join("LEFT", "userdetail", "userinfo.id=userdetail.id").Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func having(t *testing.T) {
|
||||||
|
users := make([]Userinfo, 0)
|
||||||
|
err := engine.GroupBy("username").Having("username='xlw'").Find(&users)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
fmt.Println(users)
|
||||||
|
}
|
||||||
|
|
||||||
func transaction(t *testing.T) {
|
func transaction(t *testing.T) {
|
||||||
counter := func() {
|
counter := func() {
|
||||||
total, err := engine.Count(&Userinfo{})
|
total, err := engine.Count(&Userinfo{})
|
||||||
|
@ -173,7 +230,7 @@ func transaction(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
counter()
|
counter()
|
||||||
|
defer counter()
|
||||||
session, err := engine.MakeSession()
|
session, err := engine.MakeSession()
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -181,25 +238,76 @@ func transaction(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer counter()
|
|
||||||
|
|
||||||
session.Begin()
|
session.Begin()
|
||||||
session.IsAutoRollback = true
|
//session.IsAutoRollback = false
|
||||||
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
|
user1 := Userinfo{Username: "xiaoxiao", Departname: "dev", Alias: "lunny", Created: time.Now()}
|
||||||
_, err = session.Insert(&user1)
|
_, err = session.Insert(&user1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user2 := Userinfo{Username: "yyy"}
|
user2 := Userinfo{Username: "yyy"}
|
||||||
_, err = session.Where("id = ?", 2).Update(&user2)
|
_, err = session.Where("uid = ?", 0).Update(&user2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
session.Rollback()
|
||||||
|
fmt.Println(err)
|
||||||
|
//t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = session.Delete(&user2)
|
_, err = session.Delete(&user2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = session.Commit()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func combineTransaction(t *testing.T) {
|
||||||
|
counter := func() {
|
||||||
|
total, err := engine.Count(&Userinfo{})
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("----now total %v records\n", total)
|
||||||
|
}
|
||||||
|
|
||||||
|
counter()
|
||||||
|
defer counter()
|
||||||
|
session, err := engine.MakeSession()
|
||||||
|
defer session.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
session.Begin()
|
||||||
|
//session.IsAutoRollback = false
|
||||||
|
user1 := Userinfo{Username: "xiaoxiao2", Departname: "dev", Alias: "lunny", Created: time.Now()}
|
||||||
|
_, err = session.Insert(&user1)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
user2 := Userinfo{Username: "zzz"}
|
||||||
|
_, err = session.Where("id = ?", 0).Update(&user2)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = session.Exec("delete from userinfo where username = ?", user2.Username)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -218,6 +326,8 @@ func TestMysql(t *testing.T) {
|
||||||
directCreateTable(t)
|
directCreateTable(t)
|
||||||
mapper(t)
|
mapper(t)
|
||||||
insert(t)
|
insert(t)
|
||||||
|
query(t)
|
||||||
|
exec(t)
|
||||||
insertAutoIncr(t)
|
insertAutoIncr(t)
|
||||||
insertMulti(t)
|
insertMulti(t)
|
||||||
update(t)
|
update(t)
|
||||||
|
@ -228,7 +338,10 @@ func TestMysql(t *testing.T) {
|
||||||
where(t)
|
where(t)
|
||||||
limit(t)
|
limit(t)
|
||||||
order(t)
|
order(t)
|
||||||
|
join(t)
|
||||||
|
having(t)
|
||||||
transaction(t)
|
transaction(t)
|
||||||
|
combineTransaction(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSqlite(t *testing.T) {
|
func TestSqlite(t *testing.T) {
|
||||||
|
@ -238,6 +351,8 @@ func TestSqlite(t *testing.T) {
|
||||||
directCreateTable(t)
|
directCreateTable(t)
|
||||||
mapper(t)
|
mapper(t)
|
||||||
insert(t)
|
insert(t)
|
||||||
|
query(t)
|
||||||
|
exec(t)
|
||||||
insertAutoIncr(t)
|
insertAutoIncr(t)
|
||||||
insertMulti(t)
|
insertMulti(t)
|
||||||
update(t)
|
update(t)
|
||||||
|
@ -248,5 +363,8 @@ func TestSqlite(t *testing.T) {
|
||||||
where(t)
|
where(t)
|
||||||
limit(t)
|
limit(t)
|
||||||
order(t)
|
order(t)
|
||||||
|
join(t)
|
||||||
|
having(t)
|
||||||
transaction(t)
|
transaction(t)
|
||||||
|
combineTransaction(t)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue