v0.1.4 Added simple cascade load support; added more data type supports.
This commit is contained in:
parent
75fe787648
commit
527b5b3f7a
13
README.md
13
README.md
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
[中文](https://github.com/lunny/xorm/blob/master/README_CN.md)
|
[中文](https://github.com/lunny/xorm/blob/master/README_CN.md)
|
||||||
|
|
||||||
xorm is an ORM for Go. It makes dabatabse operating simple.
|
xorm is a simple and powerful ORM for Go. It makes dabatabse operating simple.
|
||||||
|
|
||||||
It's not entirely ready for product use yet, but it's getting there.
|
It's not entirely ready for product use yet, but it's getting there.
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ Drivers for Go's sql package which currently support database/sql includes:
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
* **v0.1.4** : Added simple cascade load support; added more data type supports.
|
||||||
* **v0.1.3** : Find function now supports both slice and map; Add Table function for multi tables and temperory tables support
|
* **v0.1.3** : Find function now supports both slice and map; Add Table function for multi tables and temperory tables support
|
||||||
* **v0.1.2** : Insert function now supports both struct and slice pointer parameters, batch inserting and auto transaction
|
* **v0.1.2** : Insert function now supports both struct and slice pointer parameters, batch inserting and auto transaction
|
||||||
* **v0.1.1** : Add Id, In functions and improved README
|
* **v0.1.1** : Add Id, In functions and improved README
|
||||||
|
@ -33,6 +34,9 @@ Drivers for Go's sql package which currently support database/sql includes:
|
||||||
|
|
||||||
* Support Id, In, Where, Limit, Join, Having functions and sturct as query conditions
|
* Support Id, In, Where, Limit, Join, Having functions and sturct as query conditions
|
||||||
|
|
||||||
|
* Support simple cascade load just like Hibernate for Java
|
||||||
|
|
||||||
|
|
||||||
## Installing xorm
|
## Installing xorm
|
||||||
|
|
||||||
go get github.com/lunny/xorm
|
go get github.com/lunny/xorm
|
||||||
|
@ -111,11 +115,14 @@ var user = User{Name:"xlw"}
|
||||||
err := engine.Get(&user)
|
err := engine.Get(&user)
|
||||||
```
|
```
|
||||||
|
|
||||||
6.Fetch multipe objects, use Find:
|
6.Fetch multipe objects into a slice or a map, use Find:
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
var everyone []Userinfo
|
var everyone []Userinfo
|
||||||
err := engine.Find(&everyone)
|
err := engine.Find(&everyone)
|
||||||
|
|
||||||
|
users := make(map[int64]Userinfo)
|
||||||
|
err := engine.Find(&users)
|
||||||
```
|
```
|
||||||
|
|
||||||
6.1 also you can use Where, Limit
|
6.1 also you can use Where, Limit
|
||||||
|
@ -293,7 +300,7 @@ Another is use field tag, field tag support the below keywords which split with
|
||||||
<td>pk</td><td>the field is a primary key</td>
|
<td>pk</td><td>the field is a primary key</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>int(11)/varchar(50)</td><td>column type</td>
|
<td>int(11)/varchar(50)/text/date/datetime/blob/decimal(26,2)</td><td>column type</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>autoincr</td><td>auto incrment</td>
|
<td>autoincr</td><td>auto incrment</td>
|
||||||
|
|
|
@ -16,6 +16,7 @@ xorm是一个Go语言的ORM库. 通过它可以使数据库操作非常简便。
|
||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
|
* **v0.1.4** : Get函数和Find函数新增简单的级联载入功能;对更多的数据库类型支持。
|
||||||
* **v0.1.3** : Find函数现在支持传入Slice或者Map,当传入Map时,key为id;新增Table函数以为多表和临时表进行支持。
|
* **v0.1.3** : Find函数现在支持传入Slice或者Map,当传入Map时,key为id;新增Table函数以为多表和临时表进行支持。
|
||||||
* **v0.1.2** : Insert函数支持混合struct和slice指针传入,并根据数据库类型自动批量插入,同时自动添加事务
|
* **v0.1.2** : Insert函数支持混合struct和slice指针传入,并根据数据库类型自动批量插入,同时自动添加事务
|
||||||
* **v0.1.1** : 添加 Id, In 函数,改善 README 文档
|
* **v0.1.1** : 添加 Id, In 函数,改善 README 文档
|
||||||
|
@ -108,11 +109,14 @@ var user = User{Name:"xlw"}
|
||||||
err := engine.Get(&user)
|
err := engine.Get(&user)
|
||||||
```
|
```
|
||||||
|
|
||||||
6.获取多个对象,可以用Find方法:
|
6.获取多个对象到一个Slice或一个Map对象中,可以用Find方法:
|
||||||
|
|
||||||
```Go
|
```Go
|
||||||
var everyone []Userinfo
|
var everyone []Userinfo
|
||||||
err := engine.Find(&everyone)
|
err := engine.Find(&everyone)
|
||||||
|
|
||||||
|
users := make(map[int64]Userinfo)
|
||||||
|
err := engine.Find(&users)
|
||||||
```
|
```
|
||||||
|
|
||||||
6.1 你也可以使用Where和Limit方法设定条件和查询数量
|
6.1 你也可以使用Where和Limit方法设定条件和查询数量
|
||||||
|
@ -289,7 +293,7 @@ UserInfo中的成员UserName将会自动对应名为user_name的字段。
|
||||||
<td>pk</td><td>是否是Primary Key</td>
|
<td>pk</td><td>是否是Primary Key</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>int(11)/varchar(50)</td><td>字段类型</td>
|
<td>int(11)/varchar(50)/text/date/datetime/blob/decimal(26,2)</td><td>字段类型</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>autoincr</td><td>是否是自增</td>
|
<td>autoincr</td><td>是否是自增</td>
|
||||||
|
|
47
engine.go
47
engine.go
|
@ -16,11 +16,16 @@ const (
|
||||||
MYMYSQL = "mymysql"
|
MYMYSQL = "mymysql"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type dialect interface {
|
||||||
|
SqlType(t *Column) string
|
||||||
|
}
|
||||||
|
|
||||||
type Engine struct {
|
type Engine struct {
|
||||||
Mapper IMapper
|
Mapper IMapper
|
||||||
TagIdentifier string
|
TagIdentifier string
|
||||||
DriverName string
|
DriverName string
|
||||||
DataSourceName string
|
DataSourceName string
|
||||||
|
Dialect dialect
|
||||||
Tables map[reflect.Type]Table
|
Tables map[reflect.Type]Table
|
||||||
AutoIncrement string
|
AutoIncrement string
|
||||||
ShowSQL bool
|
ShowSQL bool
|
||||||
|
@ -119,8 +124,6 @@ func (engine *Engine) AutoMap(bean interface{}) *Table {
|
||||||
func (engine *Engine) MapType(t reflect.Type) Table {
|
func (engine *Engine) MapType(t reflect.Type) Table {
|
||||||
table := Table{Name: engine.Mapper.Obj2Table(t.Name()), Type: t}
|
table := Table{Name: engine.Mapper.Obj2Table(t.Name()), Type: t}
|
||||||
table.Columns = make(map[string]Column)
|
table.Columns = make(map[string]Column)
|
||||||
var pkCol *Column = nil
|
|
||||||
var pkstr = ""
|
|
||||||
|
|
||||||
for i := 0; i < t.NumField(); i++ {
|
for i := 0; i < t.NumField(); i++ {
|
||||||
tag := t.Field(i).Tag
|
tag := t.Field(i).Tag
|
||||||
|
@ -129,7 +132,8 @@ func (engine *Engine) MapType(t reflect.Type) Table {
|
||||||
fieldType := t.Field(i).Type
|
fieldType := t.Field(i).Type
|
||||||
|
|
||||||
if ormTagStr != "" {
|
if ormTagStr != "" {
|
||||||
col = Column{FieldName: t.Field(i).Name, Nullable: true}
|
col = Column{FieldName: t.Field(i).Name, Nullable: true, IsPrimaryKey: false,
|
||||||
|
IsAutoIncrement: false}
|
||||||
ormTagStr = strings.ToLower(ormTagStr)
|
ormTagStr = strings.ToLower(ormTagStr)
|
||||||
tags := strings.Split(ormTagStr, " ")
|
tags := strings.Split(ormTagStr, " ")
|
||||||
// TODO:
|
// TODO:
|
||||||
|
@ -143,7 +147,6 @@ func (engine *Engine) MapType(t reflect.Type) Table {
|
||||||
case k == "pk":
|
case k == "pk":
|
||||||
col.IsPrimaryKey = true
|
col.IsPrimaryKey = true
|
||||||
col.Nullable = false
|
col.Nullable = false
|
||||||
pkCol = &col
|
|
||||||
case k == "null":
|
case k == "null":
|
||||||
col.Nullable = (tags[j-1] != "not")
|
col.Nullable = (tags[j-1] != "not")
|
||||||
case k == "autoincr":
|
case k == "autoincr":
|
||||||
|
@ -158,7 +161,7 @@ func (engine *Engine) MapType(t reflect.Type) Table {
|
||||||
col.Length, _ = strconv.Atoi(lens)
|
col.Length, _ = strconv.Atoi(lens)
|
||||||
case strings.HasPrefix(k, "varchar"):
|
case strings.HasPrefix(k, "varchar"):
|
||||||
col.SQLType = Varchar
|
col.SQLType = Varchar
|
||||||
lens := k[len("decimal")+1 : len(k)-1]
|
lens := k[len("varchar")+1 : len(k)-1]
|
||||||
col.Length, _ = strconv.Atoi(lens)
|
col.Length, _ = strconv.Atoi(lens)
|
||||||
case strings.HasPrefix(k, "decimal"):
|
case strings.HasPrefix(k, "decimal"):
|
||||||
col.SQLType = Decimal
|
col.SQLType = Decimal
|
||||||
|
@ -168,6 +171,10 @@ func (engine *Engine) MapType(t reflect.Type) Table {
|
||||||
col.Length2, _ = strconv.Atoi(twolen[1])
|
col.Length2, _ = strconv.Atoi(twolen[1])
|
||||||
case k == "date":
|
case k == "date":
|
||||||
col.SQLType = Date
|
col.SQLType = Date
|
||||||
|
case k == "datetime":
|
||||||
|
col.SQLType = DateTime
|
||||||
|
case k == "timestamp":
|
||||||
|
col.SQLType = TimeStamp
|
||||||
case k == "not":
|
case k == "not":
|
||||||
default:
|
default:
|
||||||
if k != col.Default {
|
if k != col.Default {
|
||||||
|
@ -189,31 +196,23 @@ func (engine *Engine) MapType(t reflect.Type) Table {
|
||||||
if col.Name == "" {
|
if col.Name == "" {
|
||||||
col.Name = engine.Mapper.Obj2Table(t.Field(i).Name)
|
col.Name = engine.Mapper.Obj2Table(t.Field(i).Name)
|
||||||
}
|
}
|
||||||
|
if col.IsPrimaryKey {
|
||||||
|
table.PrimaryKey = col.Name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if col.Name == "" {
|
|
||||||
sqlType := Type2SQLType(fieldType)
|
sqlType := Type2SQLType(fieldType)
|
||||||
col = Column{engine.Mapper.Obj2Table(t.Field(i).Name), t.Field(i).Name, sqlType,
|
col = Column{engine.Mapper.Obj2Table(t.Field(i).Name), t.Field(i).Name, sqlType,
|
||||||
sqlType.DefaultLength, sqlType.DefaultLength2, true, "", false, false, false}
|
sqlType.DefaultLength, sqlType.DefaultLength2, true, "", false, false, false}
|
||||||
|
|
||||||
|
if col.Name == "id" {
|
||||||
|
col.IsPrimaryKey = true
|
||||||
|
col.IsAutoIncrement = true
|
||||||
|
col.Nullable = false
|
||||||
|
table.PrimaryKey = col.Name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
table.Columns[col.Name] = col
|
table.Columns[col.Name] = col
|
||||||
if strings.ToLower(t.Field(i).Name) == "id" {
|
|
||||||
pkstr = col.Name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if pkCol == nil {
|
|
||||||
if pkstr != "" {
|
|
||||||
col := table.Columns[pkstr]
|
|
||||||
col.IsPrimaryKey = true
|
|
||||||
col.IsAutoIncrement = true
|
|
||||||
col.Nullable = false
|
|
||||||
col.Length = Int.DefaultLength
|
|
||||||
table.PrimaryKey = col.Name
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
table.PrimaryKey = pkCol.Name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return table
|
return table
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
package xorm
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
type mysql struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db mysql) SqlType(c *Column) string {
|
||||||
|
switch t := c.SQLType; t {
|
||||||
|
case Date, DateTime, TimeStamp:
|
||||||
|
return "DATETIME"
|
||||||
|
case Varchar:
|
||||||
|
return t.Name + "(" + strconv.Itoa(c.Length) + ")"
|
||||||
|
case Decimal:
|
||||||
|
return t.Name + "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
|
||||||
|
default:
|
||||||
|
return t.Name
|
||||||
|
}
|
||||||
|
}
|
90
session.go
90
session.go
|
@ -59,6 +59,13 @@ func (session *Session) OrderBy(order string) *Session {
|
||||||
return session
|
return session
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (session *Session) Cascade(trueOrFalse ...bool) *Session {
|
||||||
|
if len(trueOrFalse) >= 1 {
|
||||||
|
session.Statement.UseCascade = trueOrFalse[0]
|
||||||
|
}
|
||||||
|
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 {
|
||||||
session.Statement.Join(join_operator, tablename, condition)
|
session.Statement.Join(join_operator, tablename, condition)
|
||||||
|
@ -130,6 +137,10 @@ func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]b
|
||||||
switch structField.Type().Kind() {
|
switch structField.Type().Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
v = data
|
v = data
|
||||||
|
case reflect.Array:
|
||||||
|
if structField.Type().Elem() == reflect.TypeOf(b) {
|
||||||
|
v = data
|
||||||
|
}
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
v = string(data)
|
v = string(data)
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
|
@ -160,20 +171,44 @@ func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]b
|
||||||
v = x
|
v = x
|
||||||
//Now only support Time type
|
//Now only support Time type
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if structField.Type().String() != "time.Time" {
|
if structField.Type().String() == "time.Time" {
|
||||||
return errors.New("unsupported struct type in Scan: " + structField.Type().String())
|
x, err := time.Parse("2006-01-02 15:04:05", string(data))
|
||||||
}
|
|
||||||
|
|
||||||
x, err := time.Parse("2006-01-02 15:04:05", string(data))
|
|
||||||
if err != nil {
|
|
||||||
x, err = time.Parse("2006-01-02 15:04:05.000 -0700", string(data))
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unsupported time format: " + string(data))
|
x, err = time.Parse("2006-01-02 15:04:05.000 -0700", string(data))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("unsupported time format: " + string(data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v = x
|
||||||
|
} else if session.Statement.UseCascade {
|
||||||
|
session.Engine.AutoMapType(structField.Type())
|
||||||
|
if _, ok := session.Engine.Tables[structField.Type()]; ok {
|
||||||
|
x, err := strconv.ParseInt(string(data), 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return errors.New("arg " + key + " as int: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
if x != 0 {
|
||||||
|
structInter := reflect.New(structField.Type())
|
||||||
|
session.Statement.Init()
|
||||||
|
err = session.Id(x).Get(structInter.Interface())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
v = structInter.Elem().Interface()
|
||||||
|
} else {
|
||||||
|
//fmt.Println("zero value of struct type " + structField.Type().String())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fmt.Println("unsupported struct type in Scan: " + structField.Type().String())
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
v = x
|
|
||||||
default:
|
default:
|
||||||
return errors.New("unsupported type in Scan: " + reflect.TypeOf(v).String())
|
return errors.New("unsupported type in Scan: " + reflect.TypeOf(v).String())
|
||||||
}
|
}
|
||||||
|
@ -205,6 +240,7 @@ func (session *Session) Exec(sql string, args ...interface{}) (sql.Result, error
|
||||||
}
|
}
|
||||||
if session.Engine.ShowSQL {
|
if session.Engine.ShowSQL {
|
||||||
fmt.Println(sql)
|
fmt.Println(sql)
|
||||||
|
fmt.Println(args)
|
||||||
}
|
}
|
||||||
if session.IsAutoCommit {
|
if session.IsAutoCommit {
|
||||||
return session.innerExec(sql, args...)
|
return session.innerExec(sql, args...)
|
||||||
|
@ -226,6 +262,8 @@ func (session *Session) Get(bean interface{}) error {
|
||||||
defer statement.Init()
|
defer statement.Init()
|
||||||
statement.Limit(1)
|
statement.Limit(1)
|
||||||
|
|
||||||
|
fmt.Println(bean)
|
||||||
|
|
||||||
sql, args := statement.genGetSql(bean)
|
sql, args := statement.genGetSql(bean)
|
||||||
resultsSlice, err := session.Query(sql, args...)
|
resultsSlice, err := session.Query(sql, args...)
|
||||||
|
|
||||||
|
@ -321,6 +359,7 @@ func (session *Session) Query(sql string, paramStr ...interface{}) (resultsSlice
|
||||||
}
|
}
|
||||||
if session.Engine.ShowSQL {
|
if session.Engine.ShowSQL {
|
||||||
fmt.Println(sql)
|
fmt.Println(sql)
|
||||||
|
fmt.Println(paramStr)
|
||||||
}
|
}
|
||||||
s, err := session.Db.Prepare(sql)
|
s, err := session.Db.Prepare(sql)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -377,9 +416,12 @@ func (session *Session) Query(sql string, paramStr ...interface{}) (resultsSlice
|
||||||
result[key] = []byte(str)
|
result[key] = []byte(str)
|
||||||
//时间类型
|
//时间类型
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
str = rawValue.Interface().(time.Time).Format("2006-01-02 15:04:05.000 -0700")
|
if aa.String() == "time.Time" {
|
||||||
result[key] = []byte(str)
|
str = rawValue.Interface().(time.Time).Format("2006-01-02 15:04:05.000 -0700")
|
||||||
|
result[key] = []byte(str)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
//default:
|
||||||
|
|
||||||
}
|
}
|
||||||
resultsSlice = append(resultsSlice, result)
|
resultsSlice = append(resultsSlice, result)
|
||||||
|
@ -465,7 +507,13 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
|
||||||
if col.IsAutoIncrement && fieldValue.Int() == 0 {
|
if col.IsAutoIncrement && fieldValue.Int() == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
args = append(args, val)
|
if table, ok := session.Engine.Tables[fieldValue.Type()]; ok {
|
||||||
|
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName)
|
||||||
|
fmt.Println(pkField.Interface())
|
||||||
|
args = append(args, pkField.Interface())
|
||||||
|
} else {
|
||||||
|
args = append(args, val)
|
||||||
|
}
|
||||||
colNames = append(colNames, col.Name)
|
colNames = append(colNames, col.Name)
|
||||||
cols = append(cols, col)
|
cols = append(cols, col)
|
||||||
colPlaces = append(colPlaces, "?")
|
colPlaces = append(colPlaces, "?")
|
||||||
|
@ -477,7 +525,12 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
|
||||||
if col.IsAutoIncrement && fieldValue.Int() == 0 {
|
if col.IsAutoIncrement && fieldValue.Int() == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
args = append(args, val)
|
if table, ok := session.Engine.Tables[fieldValue.Type()]; ok {
|
||||||
|
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName)
|
||||||
|
args = append(args, pkField.Interface())
|
||||||
|
} else {
|
||||||
|
args = append(args, val)
|
||||||
|
}
|
||||||
colPlaces = append(colPlaces, "?")
|
colPlaces = append(colPlaces, "?")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,7 +570,12 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
|
||||||
if col.IsAutoIncrement && fieldValue.Int() == 0 {
|
if col.IsAutoIncrement && fieldValue.Int() == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
args = append(args, val)
|
if table, ok := session.Engine.Tables[fieldValue.Type()]; ok {
|
||||||
|
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName)
|
||||||
|
args = append(args, pkField.Interface())
|
||||||
|
} else {
|
||||||
|
args = append(args, val)
|
||||||
|
}
|
||||||
colNames = append(colNames, col.Name)
|
colNames = append(colNames, col.Name)
|
||||||
colPlaces = append(colPlaces, "?")
|
colPlaces = append(colPlaces, "?")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package xorm
|
||||||
|
|
||||||
|
type sqlite3 struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db sqlite3) SqlType(c *Column) string {
|
||||||
|
switch t := c.SQLType; t {
|
||||||
|
case Date, DateTime, TimeStamp:
|
||||||
|
return "NUMERIC"
|
||||||
|
case Char, Varchar, Text:
|
||||||
|
return "TEXT"
|
||||||
|
case TinyInt, SmallInt, MediumInt, Int, BigInt:
|
||||||
|
return "INTEGER"
|
||||||
|
case Float, Double:
|
||||||
|
return "REAL"
|
||||||
|
case Decimal:
|
||||||
|
return "NUMERIC"
|
||||||
|
case Blob:
|
||||||
|
return "BLOB"
|
||||||
|
default:
|
||||||
|
return t.Name
|
||||||
|
}
|
||||||
|
}
|
55
statement.go
55
statement.go
|
@ -3,7 +3,7 @@ package xorm
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
//"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -21,6 +21,7 @@ type Statement struct {
|
||||||
HavingStr string
|
HavingStr string
|
||||||
ColumnStr string
|
ColumnStr string
|
||||||
AltTableName string
|
AltTableName string
|
||||||
|
UseCascade bool
|
||||||
BeanArgs []interface{}
|
BeanArgs []interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +40,7 @@ func (statement *Statement) Init() {
|
||||||
statement.WhereStr = ""
|
statement.WhereStr = ""
|
||||||
statement.Params = make([]interface{}, 0)
|
statement.Params = make([]interface{}, 0)
|
||||||
statement.OrderStr = ""
|
statement.OrderStr = ""
|
||||||
|
statement.UseCascade = true
|
||||||
statement.JoinStr = ""
|
statement.JoinStr = ""
|
||||||
statement.GroupByStr = ""
|
statement.GroupByStr = ""
|
||||||
statement.HavingStr = ""
|
statement.HavingStr = ""
|
||||||
|
@ -82,7 +84,17 @@ func BuildConditions(engine *Engine, table *Table, bean interface{}) ([]string,
|
||||||
default:
|
default:
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
args = append(args, val)
|
if table, ok := engine.Tables[fieldValue.Type()]; ok {
|
||||||
|
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumn().FieldName)
|
||||||
|
fmt.Println(pkField.Interface())
|
||||||
|
if pkField.Int() != 0 {
|
||||||
|
args = append(args, pkField.Interface())
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
args = append(args, val)
|
||||||
|
}
|
||||||
colNames = append(colNames, engine.QuoteIdentifier+col.Name+engine.QuoteIdentifier+"=?")
|
colNames = append(colNames, engine.QuoteIdentifier+col.Name+engine.QuoteIdentifier+"=?")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,38 +162,30 @@ func (statement *Statement) Having(conditions string) {
|
||||||
|
|
||||||
func (statement *Statement) genColumnStr(col *Column) string {
|
func (statement *Statement) genColumnStr(col *Column) string {
|
||||||
sql := "`" + col.Name + "` "
|
sql := "`" + col.Name + "` "
|
||||||
if col.SQLType == Date {
|
|
||||||
sql += " datetime "
|
|
||||||
} else {
|
|
||||||
if statement.Engine.DriverName == SQLITE && col.IsPrimaryKey {
|
|
||||||
sql += "integer"
|
|
||||||
} else {
|
|
||||||
sql += col.SQLType.Name
|
|
||||||
}
|
|
||||||
if statement.Engine.DriverName != SQLITE && col.SQLType != Text {
|
|
||||||
if col.SQLType != Decimal {
|
|
||||||
sql += "(" + strconv.Itoa(col.Length) + ")"
|
|
||||||
} else {
|
|
||||||
sql += "(" + strconv.Itoa(col.Length) + "," + strconv.Itoa(col.Length2) + ")"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if col.Nullable {
|
sql += statement.Engine.Dialect.SqlType(col) + " "
|
||||||
sql += " NULL "
|
|
||||||
} else {
|
|
||||||
sql += " NOT NULL "
|
|
||||||
}
|
|
||||||
//fmt.Println(key)
|
|
||||||
if col.IsPrimaryKey {
|
if col.IsPrimaryKey {
|
||||||
sql += "PRIMARY KEY "
|
sql += "PRIMARY KEY "
|
||||||
}
|
}
|
||||||
|
|
||||||
if col.IsAutoIncrement {
|
if col.IsAutoIncrement {
|
||||||
sql += statement.Engine.AutoIncrement + " "
|
sql += statement.Engine.AutoIncrement + " "
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if col.Nullable {
|
||||||
|
sql += "NULL "
|
||||||
|
} else {
|
||||||
|
sql += "NOT NULL "
|
||||||
|
}
|
||||||
|
|
||||||
if col.IsUnique {
|
if col.IsUnique {
|
||||||
sql += "Unique "
|
sql += "Unique "
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if col.Default != "" {
|
||||||
|
sql += "DEFAULT " + col.Default + " "
|
||||||
|
}
|
||||||
return sql
|
return sql
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +202,8 @@ func (statement *Statement) genCreateSQL() string {
|
||||||
sql := "CREATE TABLE IF NOT EXISTS `" + statement.TableName() + "` ("
|
sql := "CREATE TABLE IF NOT EXISTS `" + statement.TableName() + "` ("
|
||||||
for _, col := range statement.RefTable.Columns {
|
for _, col := range statement.RefTable.Columns {
|
||||||
sql += statement.genColumnStr(&col)
|
sql += statement.genColumnStr(&col)
|
||||||
sql += ","
|
sql = strings.TrimSpace(sql)
|
||||||
|
sql += ", "
|
||||||
}
|
}
|
||||||
sql = sql[:len(sql)-2] + ");"
|
sql = sql[:len(sql)-2] + ");"
|
||||||
return sql
|
return sql
|
||||||
|
|
54
table.go
54
table.go
|
@ -2,7 +2,7 @@ package xorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
//"strconv"
|
||||||
//"strings"
|
//"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -14,35 +14,49 @@ type SQLType struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Int = SQLType{"int", 11, 0}
|
TinyInt = SQLType{"TINYINT", 0, 0}
|
||||||
Char = SQLType{"char", 1, 0}
|
SmallInt = SQLType{"SMALLINT", 0, 0}
|
||||||
Bool = SQLType{"int", 1, 0}
|
MediumInt = SQLType{"MEDIUMINT", 0, 0}
|
||||||
Varchar = SQLType{"varchar", 50, 0}
|
Int = SQLType{"INT", 11, 0}
|
||||||
Text = SQLType{"text", 16, 0}
|
BigInt = SQLType{"BIGINT", 0, 0}
|
||||||
Date = SQLType{"date", 24, 0}
|
Char = SQLType{"CHAR", 1, 0}
|
||||||
Decimal = SQLType{"decimal", 26, 2}
|
Varchar = SQLType{"VARCHAR", 64, 0}
|
||||||
Float = SQLType{"float", 31, 0}
|
Text = SQLType{"TEXT", 16, 0}
|
||||||
Double = SQLType{"double", 31, 0}
|
Date = SQLType{"DATE", 24, 0}
|
||||||
|
DateTime = SQLType{"DATETIME", 0, 0}
|
||||||
|
Decimal = SQLType{"DECIMAL", 26, 2}
|
||||||
|
Float = SQLType{"FLOAT", 31, 0}
|
||||||
|
Double = SQLType{"DOUBLE", 31, 0}
|
||||||
|
Blob = SQLType{"BLOB", 0, 0}
|
||||||
|
TimeStamp = SQLType{"TIMESTAMP", 0, 0}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (sqlType SQLType) genSQL(length int) string {
|
var b byte
|
||||||
if sqlType == Date {
|
var tm time.Time
|
||||||
return " datetime "
|
|
||||||
}
|
|
||||||
return sqlType.Name + "(" + strconv.Itoa(length) + ")"
|
|
||||||
}
|
|
||||||
|
|
||||||
func Type2SQLType(t reflect.Type) (st SQLType) {
|
func Type2SQLType(t reflect.Type) (st SQLType) {
|
||||||
switch k := t.Kind(); k {
|
switch k := t.Kind(); k {
|
||||||
case reflect.Int, reflect.Int32, reflect.Int64:
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
||||||
st = Int
|
st = Int
|
||||||
|
case reflect.Int64, reflect.Uint64:
|
||||||
|
st = BigInt
|
||||||
|
case reflect.Float32:
|
||||||
|
st = Float
|
||||||
|
case reflect.Float64:
|
||||||
|
st = Double
|
||||||
|
case reflect.Complex64, reflect.Complex128:
|
||||||
|
st = Varchar
|
||||||
|
case reflect.Array, reflect.Slice:
|
||||||
|
if t.Elem() == reflect.TypeOf(b) {
|
||||||
|
st = Blob
|
||||||
|
}
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
st = Bool
|
st = TinyInt
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
st = Varchar
|
st = Varchar
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
if t == reflect.TypeOf(time.Time{}) {
|
if t == reflect.TypeOf(tm) {
|
||||||
st = Date
|
st = DateTime
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
st = Varchar
|
st = Varchar
|
||||||
|
|
11
xorm.go
11
xorm.go
|
@ -13,17 +13,14 @@ func Create(driverName string, dataSourceName string) Engine {
|
||||||
engine.InsertMany = true
|
engine.InsertMany = true
|
||||||
engine.TagIdentifier = "xorm"
|
engine.TagIdentifier = "xorm"
|
||||||
if driverName == SQLITE {
|
if driverName == SQLITE {
|
||||||
|
engine.Dialect = sqlite3{}
|
||||||
engine.AutoIncrement = "AUTOINCREMENT"
|
engine.AutoIncrement = "AUTOINCREMENT"
|
||||||
} else {
|
} else {
|
||||||
|
engine.Dialect = mysql{}
|
||||||
engine.AutoIncrement = "AUTO_INCREMENT"
|
engine.AutoIncrement = "AUTO_INCREMENT"
|
||||||
}
|
}
|
||||||
|
|
||||||
if engine.DriverName == PQSQL {
|
engine.QuoteIdentifier = "`"
|
||||||
engine.QuoteIdentifier = "\""
|
|
||||||
} else if engine.DriverName == MSSQL {
|
|
||||||
engine.QuoteIdentifier = ""
|
|
||||||
} else {
|
|
||||||
engine.QuoteIdentifier = "`"
|
|
||||||
}
|
|
||||||
return engine
|
return engine
|
||||||
}
|
}
|
||||||
|
|
36
xorm_test.go
36
xorm_test.go
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
_ "github.com/Go-SQL-Driver/MySQL"
|
_ "github.com/Go-SQL-Driver/MySQL"
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"xorm"
|
"xorm"
|
||||||
|
@ -26,15 +27,19 @@ CREATE TABLE `userdeatail` (
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type Userinfo struct {
|
type Userinfo struct {
|
||||||
Uid int `xorm:"id pk not null autoincr"`
|
Uid int64 `xorm:"id pk not null autoincr"`
|
||||||
Username string
|
Username string
|
||||||
Departname string
|
Departname string
|
||||||
Alias string `xorm:"-"`
|
Alias string `xorm:"-"`
|
||||||
Created time.Time
|
Created time.Time
|
||||||
|
Detail Userdetail `xorm:"detail_id int(11)"`
|
||||||
|
Height float64
|
||||||
|
Avatar []byte
|
||||||
|
IsMan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Userdetail struct {
|
type Userdetail struct {
|
||||||
Uid int `xorm:"id pk not null"`
|
Id int64
|
||||||
Intro string `xorm:"text"`
|
Intro string `xorm:"text"`
|
||||||
Profile string `xorm:"varchar(2000)"`
|
Profile string `xorm:"varchar(2000)"`
|
||||||
}
|
}
|
||||||
|
@ -71,7 +76,8 @@ func mapper(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func insert(t *testing.T) {
|
func insert(t *testing.T) {
|
||||||
user := Userinfo{1, "xiaolunwen", "dev", "lunny", time.Now()}
|
user := Userinfo{1, "xiaolunwen", "dev", "lunny", time.Now(),
|
||||||
|
Userdetail{Id: 1}, 1.78, []byte{1, 2, 3}, true}
|
||||||
_, err := engine.Insert(&user)
|
_, err := engine.Insert(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -98,7 +104,8 @@ func exec(t *testing.T) {
|
||||||
|
|
||||||
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(),
|
||||||
|
Detail: Userdetail{Id: 1}, Height: 1.78, Avatar: []byte{1, 2, 3}, IsMan: true}
|
||||||
_, err := engine.Insert(&user)
|
_, err := engine.Insert(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -135,8 +142,9 @@ func insertMulti(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func insertTwoTable(t *testing.T) {
|
func insertTwoTable(t *testing.T) {
|
||||||
userinfo := Userinfo{Username: "xlw3", Departname: "dev", Alias: "lunny4", Created: time.Now()}
|
userdetail := Userdetail{Id: 1, Intro: "I'm a very beautiful women.", Profile: "sfsaf"}
|
||||||
userdetail := Userdetail{Uid: 1, Intro: "I'm a very beautiful women.", Profile: "sfsaf"}
|
userinfo := Userinfo{Username: "xlw3", Departname: "dev", Alias: "lunny4", Created: time.Now(), Detail: userdetail}
|
||||||
|
|
||||||
_, err := engine.Insert(&userinfo, &userdetail)
|
_, err := engine.Insert(&userinfo, &userdetail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
@ -176,6 +184,16 @@ func get(t *testing.T) {
|
||||||
fmt.Println(user)
|
fmt.Println(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cascadeGet(t *testing.T) {
|
||||||
|
user := Userinfo{Uid: 11}
|
||||||
|
|
||||||
|
err := engine.Get(&user)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
fmt.Println(user)
|
||||||
|
}
|
||||||
|
|
||||||
func find(t *testing.T) {
|
func find(t *testing.T) {
|
||||||
users := make([]Userinfo, 0)
|
users := make([]Userinfo, 0)
|
||||||
|
|
||||||
|
@ -380,7 +398,7 @@ func createMultiTables(t *testing.T) {
|
||||||
|
|
||||||
user := &Userinfo{}
|
user := &Userinfo{}
|
||||||
session.Begin()
|
session.Begin()
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
err = session.Table(fmt.Sprintf("user_%v", i)).CreateTable(user)
|
err = session.Table(fmt.Sprintf("user_%v", i)).CreateTable(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.Rollback()
|
session.Rollback()
|
||||||
|
@ -425,6 +443,7 @@ func tableOp(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMysql(t *testing.T) {
|
func TestMysql(t *testing.T) {
|
||||||
|
// You should drop all tables before executing this testing
|
||||||
engine = xorm.Create("mysql", "root:123@/test?charset=utf8")
|
engine = xorm.Create("mysql", "root:123@/test?charset=utf8")
|
||||||
engine.ShowSQL = true
|
engine.ShowSQL = true
|
||||||
|
|
||||||
|
@ -439,6 +458,7 @@ func TestMysql(t *testing.T) {
|
||||||
update(t)
|
update(t)
|
||||||
delete(t)
|
delete(t)
|
||||||
get(t)
|
get(t)
|
||||||
|
cascadeGet(t)
|
||||||
find(t)
|
find(t)
|
||||||
findMap(t)
|
findMap(t)
|
||||||
count(t)
|
count(t)
|
||||||
|
@ -456,6 +476,7 @@ func TestMysql(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSqlite(t *testing.T) {
|
func TestSqlite(t *testing.T) {
|
||||||
|
os.Remove("./test.db")
|
||||||
engine = xorm.Create("sqlite3", "./test.db")
|
engine = xorm.Create("sqlite3", "./test.db")
|
||||||
engine.ShowSQL = true
|
engine.ShowSQL = true
|
||||||
|
|
||||||
|
@ -470,6 +491,7 @@ func TestSqlite(t *testing.T) {
|
||||||
update(t)
|
update(t)
|
||||||
delete(t)
|
delete(t)
|
||||||
get(t)
|
get(t)
|
||||||
|
cascadeGet(t)
|
||||||
find(t)
|
find(t)
|
||||||
findMap(t)
|
findMap(t)
|
||||||
count(t)
|
count(t)
|
||||||
|
|
Loading…
Reference in New Issue