Merge branch 'master' of github.com:go-xorm/xorm
This commit is contained in:
commit
c2ec7bc287
|
@ -18,7 +18,7 @@ Xorm is a simple and powerful ORM for Go.
|
||||||
|
|
||||||
* Query Cache speed up
|
* Query Cache speed up
|
||||||
|
|
||||||
* Database Reverse support, See [Xorm Tool README](https://github.com/go-xorm/xorm/blob/master/xorm/README.md)
|
* Database Reverse support, See [Xorm Tool README](https://github.com/go-xorm/cmd/blob/master/README.md)
|
||||||
|
|
||||||
* Simple cascade loading support
|
* Simple cascade loading support
|
||||||
|
|
||||||
|
@ -123,13 +123,10 @@ Or
|
||||||
|
|
||||||
Please visit [Xorm on Google Groups](https://groups.google.com/forum/#!forum/xorm)
|
Please visit [Xorm on Google Groups](https://groups.google.com/forum/#!forum/xorm)
|
||||||
|
|
||||||
# Contributors
|
# Contributing
|
||||||
|
|
||||||
If you want to pull request, please see [CONTRIBUTING](https://github.com/go-xorm/xorm/blob/master/CONTRIBUTING.md)
|
If you want to pull request, please see [CONTRIBUTING](https://github.com/go-xorm/xorm/blob/master/CONTRIBUTING.md)
|
||||||
|
|
||||||
* [Lunny](https://github.com/lunny)
|
|
||||||
* [Nashtsai](https://github.com/nashtsai)
|
|
||||||
|
|
||||||
# LICENSE
|
# LICENSE
|
||||||
|
|
||||||
BSD License
|
BSD License
|
||||||
|
|
|
@ -124,13 +124,10 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作
|
||||||
|
|
||||||
请加入QQ群:280360085 进行讨论。
|
请加入QQ群:280360085 进行讨论。
|
||||||
|
|
||||||
# 贡献者
|
## 贡献
|
||||||
|
|
||||||
如果您也想为Xorm贡献您的力量,请查看 [CONTRIBUTING](https://github.com/go-xorm/xorm/blob/master/CONTRIBUTING.md)
|
如果您也想为Xorm贡献您的力量,请查看 [CONTRIBUTING](https://github.com/go-xorm/xorm/blob/master/CONTRIBUTING.md)
|
||||||
|
|
||||||
* [Lunny](https://github.com/lunny)
|
|
||||||
* [Nashtsai](https://github.com/nashtsai)
|
|
||||||
|
|
||||||
## LICENSE
|
## LICENSE
|
||||||
|
|
||||||
BSD License
|
BSD License
|
||||||
|
|
|
@ -58,7 +58,7 @@ engine, err = xorm.NewEngine("sqlite3", "./test.db")
|
||||||
defer engine.Close()
|
defer engine.Close()
|
||||||
```
|
```
|
||||||
|
|
||||||
Generally, you can only create one engine. Engine supports run on go rutines.
|
You can create many engines for different databases.Generally, you just need create only one engine. Engine supports run on go routines.
|
||||||
|
|
||||||
xorm supports four drivers now:
|
xorm supports four drivers now:
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ engine.Cols("age", "name").Update(&user)
|
||||||
* Omit(...string)
|
* Omit(...string)
|
||||||
和cols相反,此函数指定排除某些指定的字段。注意:此方法和Cols方法不可同时使用
|
和cols相反,此函数指定排除某些指定的字段。注意:此方法和Cols方法不可同时使用
|
||||||
```Go
|
```Go
|
||||||
engine.Cols("age").Update(&user)
|
engine.Omit("age").Update(&user)
|
||||||
// UPDATE user SET name = ? AND department = ?
|
// UPDATE user SET name = ? AND department = ?
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,7 @@ engine, err = xorm.NewEngine("sqlite3", "./test.db")
|
||||||
defer engine.Close()
|
defer engine.Close()
|
||||||
```
|
```
|
||||||
|
|
||||||
一般如果只针对一个数据库进行操作,只需要创建一个Engine即可。Engine支持在多GoRutine下使用。
|
你可以创建一个或多个engine, 不过一般如果操作一个数据库,只需要创建一个Engine即可。Engine支持在多GoRutine下使用。
|
||||||
|
|
||||||
xorm当前支持五种驱动四个数据库如下:
|
xorm当前支持五种驱动四个数据库如下:
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ engine.Cols("age", "name").Update(&user)
|
||||||
* Omit(...string)
|
* Omit(...string)
|
||||||
和cols相反,此函数指定排除某些指定的字段。注意:此方法和Cols方法不可同时使用
|
和cols相反,此函数指定排除某些指定的字段。注意:此方法和Cols方法不可同时使用
|
||||||
```Go
|
```Go
|
||||||
engine.Cols("age").Update(&user)
|
engine.Omit("age").Update(&user)
|
||||||
// UPDATE user SET name = ? AND department = ?
|
// UPDATE user SET name = ? AND department = ?
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
96
engine.go
96
engine.go
|
@ -6,6 +6,7 @@ import (
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -34,8 +35,7 @@ type Engine struct {
|
||||||
ShowErr bool
|
ShowErr bool
|
||||||
ShowDebug bool
|
ShowDebug bool
|
||||||
ShowWarn bool
|
ShowWarn bool
|
||||||
//Pool IConnectPool
|
|
||||||
//Filters []core.Filter
|
|
||||||
Logger ILogger // io.Writer
|
Logger ILogger // io.Writer
|
||||||
TZLocation *time.Location
|
TZLocation *time.Location
|
||||||
}
|
}
|
||||||
|
@ -266,6 +266,77 @@ func (engine *Engine) DBMetas() ([]*core.Table, error) {
|
||||||
return tables, nil
|
return tables, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (engine *Engine) DumpAllToFile(fp string) error {
|
||||||
|
f, err := os.Create(fp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
return engine.DumpAll(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (engine *Engine) DumpAll(w io.Writer) error {
|
||||||
|
tables, err := engine.DBMetas()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, table := range tables {
|
||||||
|
_, err = io.WriteString(w, engine.dialect.CreateTableSql(table, "", "", "")+"\n\n")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, index := range table.Indexes {
|
||||||
|
_, err = io.WriteString(w, engine.dialect.CreateIndexSql(table.Name, index)+"\n\n")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rows, err := engine.DB().Query("SELECT * FROM " + engine.Quote(table.Name))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cols, err := rows.Columns()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(cols) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for rows.Next() {
|
||||||
|
dest := make([]interface{}, len(cols))
|
||||||
|
err = rows.ScanSlice(&dest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.WriteString(w, "INSERT INTO "+engine.Quote(table.Name)+" ("+engine.Quote(strings.Join(cols, engine.Quote(", ")))+") VALUES (")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var temp string
|
||||||
|
for _, d := range dest {
|
||||||
|
if d == nil {
|
||||||
|
temp += ", NULL"
|
||||||
|
} else if reflect.TypeOf(d).Kind() == reflect.String {
|
||||||
|
temp += ", '" + strings.Replace(d.(string), "'", "''", -1) + "'"
|
||||||
|
} else if reflect.TypeOf(d).Kind() == reflect.Slice {
|
||||||
|
temp += fmt.Sprintf(", %s", engine.dialect.FormatBytes(d.([]byte)))
|
||||||
|
} else {
|
||||||
|
temp += fmt.Sprintf(", %v", d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = io.WriteString(w, temp[2:]+");\n\n")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// use cascade or not
|
// use cascade or not
|
||||||
func (engine *Engine) Cascade(trueOrFalse ...bool) *Session {
|
func (engine *Engine) Cascade(trueOrFalse ...bool) *Session {
|
||||||
session := engine.NewSession()
|
session := engine.NewSession()
|
||||||
|
@ -456,15 +527,6 @@ func (engine *Engine) autoMap(bean interface{}) *core.Table {
|
||||||
return engine.autoMapType(v)
|
return engine.autoMapType(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*func (engine *Engine) mapType(t reflect.Type) *core.Table {
|
|
||||||
return mappingTable(t, engine.TableMapper, engine.ColumnMapper, engine.dialect, engine.TagIdentifier)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
func mappingTable(t reflect.Type, tableMapper core.IMapper, colMapper core.IMapper, dialect core.Dialect, tagId string) *core.Table {
|
|
||||||
table := core.NewEmptyTable()
|
|
||||||
table.Name = tableMapper.Obj2Table(t.Name())
|
|
||||||
*/
|
|
||||||
func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) {
|
func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) {
|
||||||
if index, ok := table.Indexes[indexName]; ok {
|
if index, ok := table.Indexes[indexName]; ok {
|
||||||
index.AddColumn(col.Name)
|
index.AddColumn(col.Name)
|
||||||
|
@ -524,18 +586,20 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
|
||||||
if tags[0] == "-" {
|
if tags[0] == "-" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (strings.ToUpper(tags[0]) == "EXTENDS") &&
|
if strings.ToUpper(tags[0]) == "EXTENDS" {
|
||||||
(fieldType.Kind() == reflect.Struct) {
|
fieldValue = reflect.Indirect(fieldValue)
|
||||||
|
if fieldValue.Kind() == reflect.Struct {
|
||||||
//parentTable := mappingTable(fieldType, tableMapper, colMapper, dialect, tagId)
|
//parentTable := mappingTable(fieldType, tableMapper, colMapper, dialect, tagId)
|
||||||
parentTable := engine.mapType(fieldValue)
|
parentTable := engine.mapType(fieldValue)
|
||||||
for _, col := range parentTable.Columns() {
|
for _, col := range parentTable.Columns() {
|
||||||
col.FieldName = fmt.Sprintf("%v.%v", fieldType.Name(), col.FieldName)
|
col.FieldName = fmt.Sprintf("%v.%v", fieldValue.Type().Name(), col.FieldName)
|
||||||
table.AddColumn(col)
|
table.AddColumn(col)
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
//TODO: warning
|
||||||
|
}
|
||||||
|
|
||||||
indexNames := make(map[string]int)
|
indexNames := make(map[string]int)
|
||||||
var isIndex, isUnique bool
|
var isIndex, isUnique bool
|
||||||
|
@ -701,7 +765,7 @@ func (engine *Engine) IsTableEmpty(bean interface{}) (bool, error) {
|
||||||
session := engine.NewSession()
|
session := engine.NewSession()
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
rows, err := session.Count(bean)
|
rows, err := session.Count(bean)
|
||||||
return rows > 0, err
|
return rows == 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a table is exist
|
// If a table is exist
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/go-xorm/xorm"
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
if len(os.Args) < 2 {
|
||||||
|
fmt.Println("need db path")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
orm, err := xorm.NewEngine("sqlite3", os.Args[1])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer orm.Close()
|
||||||
|
orm.ShowSQL = true
|
||||||
|
|
||||||
|
tables, err := orm.DBMetas()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, table := range tables {
|
||||||
|
fmt.Println(table.Name)
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,10 @@ type BeforeDeleteProcessor interface {
|
||||||
BeforeDelete()
|
BeforeDelete()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BeforeSetProcessor interface {
|
||||||
|
BeforeSet(string, Cell)
|
||||||
|
}
|
||||||
|
|
||||||
// !nashtsai! TODO enable BeforeValidateProcessor when xorm start to support validations
|
// !nashtsai! TODO enable BeforeValidateProcessor when xorm start to support validations
|
||||||
//// Executed before an object is validated
|
//// Executed before an object is validated
|
||||||
//type BeforeValidateProcessor interface {
|
//type BeforeValidateProcessor interface {
|
||||||
|
|
67
session.go
67
session.go
|
@ -883,7 +883,6 @@ func (session *Session) Rows(bean interface{}) (*Rows, error) {
|
||||||
// are conditions. beans could be []Struct, []*Struct, map[int64]Struct
|
// are conditions. beans could be []Struct, []*Struct, map[int64]Struct
|
||||||
// map[int64]*Struct
|
// map[int64]*Struct
|
||||||
func (session *Session) Iterate(bean interface{}, fun IterFunc) error {
|
func (session *Session) Iterate(bean interface{}, fun IterFunc) error {
|
||||||
|
|
||||||
rows, err := session.Rows(bean)
|
rows, err := session.Rows(bean)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -982,24 +981,6 @@ func (session *Session) Get(bean interface{}) (bool, error) {
|
||||||
} else {
|
} else {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// resultsSlice, err := session.query(sqlStr, args...)
|
|
||||||
// if err != nil {
|
|
||||||
// return false, err
|
|
||||||
// }
|
|
||||||
// if len(resultsSlice) < 1 {
|
|
||||||
// return false, nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// err = session.scanMapIntoStruct(bean, resultsSlice[0])
|
|
||||||
// if err != nil {
|
|
||||||
// return true, err
|
|
||||||
// }
|
|
||||||
// if len(resultsSlice) == 1 {
|
|
||||||
// return true, nil
|
|
||||||
// } else {
|
|
||||||
// return true, errors.New("More than one record")
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Count counts the records. bean's non-empty fields
|
// Count counts the records. bean's non-empty fields
|
||||||
|
@ -1441,6 +1422,8 @@ func (session *Session) getField(dataStruct *reflect.Value, key string, table *c
|
||||||
return fieldValue
|
return fieldValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Cell *interface{}
|
||||||
|
|
||||||
func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}) error {
|
func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}) error {
|
||||||
dataStruct := rValue(bean)
|
dataStruct := rValue(bean)
|
||||||
if dataStruct.Kind() != reflect.Struct {
|
if dataStruct.Kind() != reflect.Struct {
|
||||||
|
@ -1449,18 +1432,24 @@ func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount i
|
||||||
|
|
||||||
table := session.Engine.autoMapType(dataStruct)
|
table := session.Engine.autoMapType(dataStruct)
|
||||||
|
|
||||||
scanResultContainers := make([]interface{}, len(fields))
|
scanResults := make([]interface{}, len(fields))
|
||||||
for i := 0; i < len(fields); i++ {
|
for i := 0; i < len(fields); i++ {
|
||||||
var scanResultContainer interface{}
|
var cell interface{}
|
||||||
scanResultContainers[i] = &scanResultContainer
|
scanResults[i] = &cell
|
||||||
}
|
}
|
||||||
if err := rows.Scan(scanResultContainers...); err != nil {
|
if err := rows.Scan(scanResults...); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b, hasBeforeSet := bean.(BeforeSetProcessor)
|
||||||
|
|
||||||
for ii, key := range fields {
|
for ii, key := range fields {
|
||||||
|
if hasBeforeSet {
|
||||||
|
b.BeforeSet(fields[ii], Cell(scanResults[ii].(*interface{})))
|
||||||
|
}
|
||||||
|
|
||||||
if fieldValue := session.getField(&dataStruct, key, table); fieldValue != nil {
|
if fieldValue := session.getField(&dataStruct, key, table); fieldValue != nil {
|
||||||
rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii]))
|
rawValue := reflect.Indirect(reflect.ValueOf(scanResults[ii]))
|
||||||
|
|
||||||
//if row is null then ignore
|
//if row is null then ignore
|
||||||
if rawValue.Interface() == nil {
|
if rawValue.Interface() == nil {
|
||||||
|
@ -1468,6 +1457,7 @@ func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount i
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fieldValue.CanAddr() {
|
||||||
if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
|
if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
|
||||||
if data, err := value2Bytes(&rawValue); err == nil {
|
if data, err := value2Bytes(&rawValue); err == nil {
|
||||||
structConvert.FromDB(data)
|
structConvert.FromDB(data)
|
||||||
|
@ -1476,6 +1466,16 @@ func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount i
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if structConvert, ok := fieldValue.Interface().(core.Conversion); ok {
|
||||||
|
if data, err := value2Bytes(&rawValue); err == nil {
|
||||||
|
structConvert.FromDB(data)
|
||||||
|
} else {
|
||||||
|
session.Engine.LogError(err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
rawValueType := reflect.TypeOf(rawValue.Interface())
|
rawValueType := reflect.TypeOf(rawValue.Interface())
|
||||||
vv := reflect.ValueOf(rawValue.Interface())
|
vv := reflect.ValueOf(rawValue.Interface())
|
||||||
|
@ -2451,6 +2451,16 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fieldConvert, ok := fieldValue.Interface().(core.Conversion); ok {
|
||||||
|
data, err := fieldConvert.ToDB()
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
} else {
|
||||||
|
return string(data), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fieldType := fieldValue.Type()
|
fieldType := fieldValue.Type()
|
||||||
k := fieldType.Kind()
|
k := fieldType.Kind()
|
||||||
if k == reflect.Ptr {
|
if k == reflect.Ptr {
|
||||||
|
@ -2470,11 +2480,6 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val
|
||||||
switch k {
|
switch k {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
return fieldValue.Bool(), nil
|
return fieldValue.Bool(), nil
|
||||||
/*if fieldValue.Bool() {
|
|
||||||
return 1, nil
|
|
||||||
} else {
|
|
||||||
return 0, nil
|
|
||||||
}*/
|
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return fieldValue.String(), nil
|
return fieldValue.String(), nil
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
|
@ -2947,7 +2952,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
|
||||||
session.Statement.RefTable = table
|
session.Statement.RefTable = table
|
||||||
|
|
||||||
if session.Statement.ColumnStr == "" {
|
if session.Statement.ColumnStr == "" {
|
||||||
colNames, args = buildConditions(session.Engine, table, bean, false, false,
|
colNames, args = buildUpdates(session.Engine, table, bean, false, false,
|
||||||
false, false, session.Statement.allUseBool, session.Statement.useAllCols,
|
false, false, session.Statement.allUseBool, session.Statement.useAllCols,
|
||||||
session.Statement.mustColumnMap)
|
session.Statement.mustColumnMap)
|
||||||
} else {
|
} else {
|
||||||
|
@ -3314,7 +3319,7 @@ func genCols(table *core.Table, session *Session, bean interface{}, useCol bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (col.IsCreated || col.IsUpdated) && session.Statement.UseAutoTime {
|
if (col.IsCreated || col.IsUpdated) && session.Statement.UseAutoTime {
|
||||||
args = append(args, time.Now())
|
args = append(args, session.Engine.NowTime(col.SQLType.Name))
|
||||||
} else if col.IsVersion && session.Statement.checkVersion {
|
} else if col.IsVersion && session.Statement.checkVersion {
|
||||||
args = append(args, 1)
|
args = append(args, 1)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package xorm
|
package xorm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/go-xorm/core"
|
"github.com/go-xorm/core"
|
||||||
|
@ -44,6 +45,10 @@ func (db *sqlite3) SqlType(c *core.Column) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (db *sqlite3) FormatBytes(bs []byte) string {
|
||||||
|
return fmt.Sprintf("X'%x'", bs)
|
||||||
|
}
|
||||||
|
|
||||||
func (db *sqlite3) SupportInsertMany() bool {
|
func (db *sqlite3) SupportInsertMany() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
207
statement.go
207
statement.go
|
@ -253,6 +253,197 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
|
||||||
return results
|
return results
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
// Auto generating conditions according a struct
|
||||||
|
func buildUpdates(engine *Engine, table *core.Table, bean interface{},
|
||||||
|
includeVersion bool, includeUpdated bool, includeNil bool,
|
||||||
|
includeAutoIncr bool, allUseBool bool, useAllCols bool,
|
||||||
|
mustColumnMap map[string]bool) ([]string, []interface{}) {
|
||||||
|
|
||||||
|
colNames := make([]string, 0)
|
||||||
|
var args = make([]interface{}, 0)
|
||||||
|
for _, col := range table.Columns() {
|
||||||
|
if !includeVersion && col.IsVersion {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if col.IsCreated {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !includeUpdated && col.IsUpdated {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !includeAutoIncr && col.IsAutoIncrement {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//fmt.Println(engine.dialect.DBType(), Text)
|
||||||
|
if engine.dialect.DBType() == core.MSSQL && col.SQLType.Name == core.Text {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fieldValuePtr, err := col.ValueOf(bean)
|
||||||
|
if err != nil {
|
||||||
|
engine.LogError(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldValue := *fieldValuePtr
|
||||||
|
fieldType := reflect.TypeOf(fieldValue.Interface())
|
||||||
|
|
||||||
|
requiredField := useAllCols
|
||||||
|
if b, ok := mustColumnMap[strings.ToLower(col.Name)]; ok {
|
||||||
|
if b {
|
||||||
|
requiredField = true
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var val interface{}
|
||||||
|
|
||||||
|
if fieldValue.CanAddr() {
|
||||||
|
if structConvert, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
|
||||||
|
data, err := structConvert.ToDB()
|
||||||
|
if err != nil {
|
||||||
|
engine.LogError(err)
|
||||||
|
} else {
|
||||||
|
val = data
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if structConvert, ok := fieldValue.Interface().(core.Conversion); ok {
|
||||||
|
data, err := structConvert.ToDB()
|
||||||
|
if err != nil {
|
||||||
|
engine.LogError(err)
|
||||||
|
} else {
|
||||||
|
val = data
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if fieldType.Kind() == reflect.Ptr {
|
||||||
|
if fieldValue.IsNil() {
|
||||||
|
if includeNil {
|
||||||
|
args = append(args, nil)
|
||||||
|
colNames = append(colNames, fmt.Sprintf("%v=?", engine.Quote(col.Name)))
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else if !fieldValue.IsValid() {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
// dereference ptr type to instance type
|
||||||
|
fieldValue = fieldValue.Elem()
|
||||||
|
fieldType = reflect.TypeOf(fieldValue.Interface())
|
||||||
|
requiredField = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch fieldType.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
if allUseBool || requiredField {
|
||||||
|
val = fieldValue.Interface()
|
||||||
|
} else {
|
||||||
|
// if a bool in a struct, it will not be as a condition because it default is false,
|
||||||
|
// please use Where() instead
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case reflect.String:
|
||||||
|
if !requiredField && fieldValue.String() == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// for MyString, should convert to string or panic
|
||||||
|
if fieldType.String() != reflect.String.String() {
|
||||||
|
val = fieldValue.String()
|
||||||
|
} else {
|
||||||
|
val = fieldValue.Interface()
|
||||||
|
}
|
||||||
|
case reflect.Int8, reflect.Int16, reflect.Int, reflect.Int32, reflect.Int64:
|
||||||
|
if !requiredField && fieldValue.Int() == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val = fieldValue.Interface()
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
if !requiredField && fieldValue.Float() == 0.0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val = fieldValue.Interface()
|
||||||
|
case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64:
|
||||||
|
if !requiredField && fieldValue.Uint() == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val = fieldValue.Interface()
|
||||||
|
case reflect.Struct:
|
||||||
|
if fieldType == reflect.TypeOf(time.Now()) {
|
||||||
|
t := fieldValue.Interface().(time.Time)
|
||||||
|
if !requiredField && (t.IsZero() || !fieldValue.IsValid()) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val = engine.FormatTime(col.SQLType.Name, t)
|
||||||
|
//fmt.Println("-------", t, val, col.Name)
|
||||||
|
} else {
|
||||||
|
engine.autoMapType(fieldValue)
|
||||||
|
if table, ok := engine.Tables[fieldValue.Type()]; ok {
|
||||||
|
if len(table.PrimaryKeys) == 1 {
|
||||||
|
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName)
|
||||||
|
if pkField.Int() != 0 {
|
||||||
|
val = pkField.Interface()
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//TODO: how to handler?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val = fieldValue.Interface()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case reflect.Array, reflect.Slice, reflect.Map:
|
||||||
|
if fieldValue == reflect.Zero(fieldType) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if col.SQLType.IsText() {
|
||||||
|
bytes, err := json.Marshal(fieldValue.Interface())
|
||||||
|
if err != nil {
|
||||||
|
engine.LogError(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val = string(bytes)
|
||||||
|
} else if col.SQLType.IsBlob() {
|
||||||
|
var bytes []byte
|
||||||
|
var err error
|
||||||
|
if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) &&
|
||||||
|
fieldType.Elem().Kind() == reflect.Uint8 {
|
||||||
|
if fieldValue.Len() > 0 {
|
||||||
|
val = fieldValue.Bytes()
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bytes, err = json.Marshal(fieldValue.Interface())
|
||||||
|
if err != nil {
|
||||||
|
engine.LogError(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val = bytes
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
val = fieldValue.Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
args = append(args, val)
|
||||||
|
colNames = append(colNames, fmt.Sprintf("%v=?", engine.Quote(col.Name)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return colNames, args
|
||||||
|
}
|
||||||
|
|
||||||
// Auto generating conditions according a struct
|
// Auto generating conditions according a struct
|
||||||
func buildConditions(engine *Engine, table *core.Table, bean interface{},
|
func buildConditions(engine *Engine, table *core.Table, bean interface{},
|
||||||
includeVersion bool, includeUpdated bool, includeNil bool,
|
includeVersion bool, includeUpdated bool, includeNil bool,
|
||||||
|
@ -283,8 +474,11 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{},
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldValue := *fieldValuePtr
|
fieldValue := *fieldValuePtr
|
||||||
fieldType := reflect.TypeOf(fieldValue.Interface())
|
if fieldValue.Interface() == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldType := reflect.TypeOf(fieldValue.Interface())
|
||||||
requiredField := useAllCols
|
requiredField := useAllCols
|
||||||
if b, ok := mustColumnMap[strings.ToLower(col.Name)]; ok {
|
if b, ok := mustColumnMap[strings.ToLower(col.Name)]; ok {
|
||||||
if b {
|
if b {
|
||||||
|
@ -353,7 +547,7 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{},
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
val = engine.FormatTime(col.SQLType.Name, t)
|
val = engine.FormatTime(col.SQLType.Name, t)
|
||||||
fmt.Println("-------", t, val, col.Name)
|
//fmt.Println("-------", t, val, col.Name)
|
||||||
} else {
|
} else {
|
||||||
engine.autoMapType(fieldValue)
|
engine.autoMapType(fieldValue)
|
||||||
if table, ok := engine.Tables[fieldValue.Type()]; ok {
|
if table, ok := engine.Tables[fieldValue.Type()]; ok {
|
||||||
|
@ -762,11 +956,12 @@ func (statement *Statement) genCountSql(bean interface{}) (string, []interface{}
|
||||||
statement.ConditionStr = strings.Join(colNames, " AND ")
|
statement.ConditionStr = strings.Join(colNames, " AND ")
|
||||||
statement.BeanArgs = args
|
statement.BeanArgs = args
|
||||||
// count(index fieldname) > count(0) > count(*)
|
// count(index fieldname) > count(0) > count(*)
|
||||||
var id string = "0"
|
// for compitable on kinds of database, just use *
|
||||||
|
/*var id string = "0"
|
||||||
if len(table.PrimaryKeys) == 1 {
|
if len(table.PrimaryKeys) == 1 {
|
||||||
id = statement.Engine.Quote(table.PrimaryKeys[0])
|
id = statement.Engine.Quote(statement.TableName()) + "." + statement.Engine.Quote(table.PrimaryKeys[0])
|
||||||
}
|
}*/
|
||||||
return statement.genSelectSql(fmt.Sprintf("COUNT(%v) AS %v", id, statement.Engine.Quote("total"))), append(statement.Params, statement.BeanArgs...)
|
return statement.genSelectSql(fmt.Sprintf("COUNT(*) AS %v", statement.Engine.Quote("total"))), append(statement.Params, statement.BeanArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (statement *Statement) genSelectSql(columnStr string) (a string) {
|
func (statement *Statement) genSelectSql(columnStr string) (a string) {
|
||||||
|
|
Loading…
Reference in New Issue