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()
```
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:

View File

@ -62,7 +62,7 @@ engine, err = xorm.NewEngine("sqlite3", "./test.db")
defer engine.Close()
```
一般如果只针对一个数据库进行操作只需要创建一个Engine即可。Engine支持在多GoRutine下使用。
你可以创建一个或多个engine, 不过一般如果操作一个数据库只需要创建一个Engine即可。Engine支持在多GoRutine下使用。
xorm当前支持五种驱动四个数据库如下

View File

@ -34,8 +34,7 @@ type Engine struct {
ShowErr bool
ShowDebug bool
ShowWarn bool
//Pool IConnectPool
//Filters []core.Filter
Logger ILogger // io.Writer
TZLocation *time.Location
}
@ -456,15 +455,6 @@ func (engine *Engine) autoMap(bean interface{}) *core.Table {
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) {
if index, ok := table.Indexes[indexName]; ok {
index.AddColumn(col.Name)
@ -524,18 +514,20 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
if tags[0] == "-" {
continue
}
if (strings.ToUpper(tags[0]) == "EXTENDS") &&
(fieldType.Kind() == reflect.Struct) {
if strings.ToUpper(tags[0]) == "EXTENDS" {
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", fieldType.Name(), col.FieldName)
col.FieldName = fmt.Sprintf("%v.%v", fieldValue.Type().Name(), col.FieldName)
table.AddColumn(col)
}
continue
}
//TODO: warning
}
indexNames := make(map[string]int)
var isIndex, isUnique bool
@ -701,7 +693,7 @@ func (engine *Engine) IsTableEmpty(bean interface{}) (bool, error) {
session := engine.NewSession()
defer session.Close()
rows, err := session.Count(bean)
return rows > 0, err
return rows == 0, err
}
// If a table is exist

View File

@ -2947,7 +2947,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
session.Statement.RefTable = table
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,
session.Statement.mustColumnMap)
} else {

View File

@ -253,6 +253,174 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
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
func buildConditions(engine *Engine, table *core.Table, bean interface{},
includeVersion bool, includeUpdated bool, includeNil bool,