bug fixed and docs improved

This commit is contained in:
Lunny Xiao 2014-05-02 08:48:51 +08:00
parent f3fc0b9976
commit 685a4a63fd
5 changed files with 184 additions and 24 deletions

View File

@ -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 routines. 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:

View File

@ -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当前支持五种驱动四个数据库如下

View File

@ -34,8 +34,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
} }
@ -456,15 +455,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,17 +514,19 @@ 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 := engine.mapType(fieldValue)
for _, col := range parentTable.Columns() {
col.FieldName = fmt.Sprintf("%v.%v", fieldValue.Type().Name(), col.FieldName)
table.AddColumn(col)
}
//parentTable := mappingTable(fieldType, tableMapper, colMapper, dialect, tagId) continue
parentTable := engine.mapType(fieldValue)
for _, col := range parentTable.Columns() {
col.FieldName = fmt.Sprintf("%v.%v", fieldType.Name(), col.FieldName)
table.AddColumn(col)
} }
//TODO: warning
continue
} }
indexNames := make(map[string]int) indexNames := make(map[string]int)
@ -701,7 +693,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

View File

@ -2947,7 +2947,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 {

View File

@ -253,6 +253,174 @@ 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
}
}
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
}
}
var val interface{}
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,