bug fixed and performance improved for table name

This commit is contained in:
Lunny Xiao 2016-07-09 08:15:53 +08:00
parent 86701ad07e
commit 5612916fea
6 changed files with 159 additions and 190 deletions

View File

@ -1 +1 @@
xorm v0.5.5.0707 xorm v0.5.5.0709

126
engine.go
View File

@ -286,46 +286,6 @@ func (engine *Engine) logSQLExecutionTime(sqlStr string, args []interface{}, exe
} }
} }
// LogError logging error
/*func (engine *Engine) LogError(contents ...interface{}) {
engine.logger.Err(contents...)
}
// LogErrorf logging errorf
func (engine *Engine) LogErrorf(format string, contents ...interface{}) {
engine.logger.Errf(format, contents...)
}
// LogInfo logging info
func (engine *Engine) LogInfo(contents ...interface{}) {
engine.logger.Info(contents...)
}
// LogInfof logging infof
func (engine *Engine) LogInfof(format string, contents ...interface{}) {
engine.logger.Infof(format, contents...)
}
// LogDebug logging debug
func (engine *Engine) LogDebug(contents ...interface{}) {
engine.logger.Debug(contents...)
}
// LogDebugf logging debugf
func (engine *Engine) LogDebugf(format string, contents ...interface{}) {
engine.logger.Debugf(format, contents...)
}
// LogWarn logging warn
func (engine *Engine) LogWarn(contents ...interface{}) {
engine.logger.Warning(contents...)
}
// LogWarnf logging warnf
func (engine *Engine) LogWarnf(format string, contents ...interface{}) {
engine.logger.Warningf(format, contents...)
}*/
// Sql method let's you manualy write raw sql and operate // Sql method let's you manualy write raw sql and operate
// For example: // For example:
// //
@ -421,8 +381,26 @@ func (engine *Engine) DumpTables(tables []*core.Table, w io.Writer, tp ...core.D
return engine.dumpTables(tables, w, tp...) return engine.dumpTables(tables, w, tp...)
} }
func (engine *Engine) tbName(tb *core.Table) string { func (engine *Engine) tableName(beanOrTableName interface{}) (string, error) {
return tb.Name v := rValue(beanOrTableName)
if v.Type().Kind() == reflect.String {
return beanOrTableName.(string), nil
} else if v.Type().Kind() == reflect.Struct {
return engine.tbName(v), nil
}
return "", errors.New("bean should be a struct or struct's point")
}
func (engine *Engine) tbName(v reflect.Value) string {
if tb, ok := v.Interface().(TableName); ok {
return tb.TableName()
}
if v.CanAddr() {
if tb, ok := v.Addr().Interface().(TableName); ok {
return tb.TableName()
}
}
return engine.TableMapper.Obj2Table(v.Type().Name())
} }
// DumpAll dump database all table structs and data to w with specify db type // DumpAll dump database all table structs and data to w with specify db type
@ -461,16 +439,17 @@ func (engine *Engine) dumpAll(w io.Writer, tp ...core.DbType) error {
return err return err
} }
for _, index := range table.Indexes { for _, index := range table.Indexes {
_, err = io.WriteString(w, dialect.CreateIndexSql(engine.tbName(table), index)+";\n") _, err = io.WriteString(w, dialect.CreateIndexSql(table.Name, index)+";\n")
if err != nil { if err != nil {
return err return err
} }
} }
rows, err := engine.DB().Query("SELECT * FROM " + engine.Quote(engine.tbName(table))) rows, err := engine.DB().Query("SELECT * FROM " + engine.Quote(table.Name))
if err != nil { if err != nil {
return err return err
} }
defer rows.Close()
cols, err := rows.Columns() cols, err := rows.Columns()
if err != nil { if err != nil {
@ -486,7 +465,7 @@ func (engine *Engine) dumpAll(w io.Writer, tp ...core.DbType) error {
return err return err
} }
_, err = io.WriteString(w, "INSERT INTO "+dialect.Quote(engine.tbName(table))+" ("+dialect.Quote(strings.Join(cols, dialect.Quote(", ")))+") VALUES (") _, err = io.WriteString(w, "INSERT INTO "+dialect.Quote(table.Name)+" ("+dialect.Quote(strings.Join(cols, dialect.Quote(", ")))+") VALUES (")
if err != nil { if err != nil {
return err return err
} }
@ -561,16 +540,17 @@ func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.D
return err return err
} }
for _, index := range table.Indexes { for _, index := range table.Indexes {
_, err = io.WriteString(w, dialect.CreateIndexSql(engine.tbName(table), index)+";\n") _, err = io.WriteString(w, dialect.CreateIndexSql(table.Name, index)+";\n")
if err != nil { if err != nil {
return err return err
} }
} }
rows, err := engine.DB().Query("SELECT * FROM " + engine.Quote(engine.tbName(table))) rows, err := engine.DB().Query("SELECT * FROM " + engine.Quote(table.Name))
if err != nil { if err != nil {
return err return err
} }
defer rows.Close()
cols, err := rows.Columns() cols, err := rows.Columns()
if err != nil { if err != nil {
@ -586,7 +566,7 @@ func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.D
return err return err
} }
_, err = io.WriteString(w, "INSERT INTO "+dialect.Quote(engine.tbName(table))+" ("+dialect.Quote(strings.Join(cols, dialect.Quote(", ")))+") VALUES (") _, err = io.WriteString(w, "INSERT INTO "+dialect.Quote(table.Name)+" ("+dialect.Quote(strings.Join(cols, dialect.Quote(", ")))+") VALUES (")
if err != nil { if err != nil {
return err return err
} }
@ -868,9 +848,14 @@ func (engine *Engine) GobRegister(v interface{}) *Engine {
return engine return engine
} }
func (engine *Engine) TableInfo(bean interface{}) *core.Table { type Table struct {
*core.Table
Name string
}
func (engine *Engine) TableInfo(bean interface{}) *Table {
v := rValue(bean) v := rValue(bean)
return engine.autoMapType(v) return &Table{engine.autoMapType(v), engine.tbName(v)}
} }
func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) { func addIndex(indexName string, table *core.Table, col *core.Column, indexType int) {
@ -1247,18 +1232,20 @@ func (engine *Engine) getCacher(v reflect.Value) core.Cacher {
// If enabled cache, clear the cache bean // If enabled cache, clear the cache bean
func (engine *Engine) ClearCacheBean(bean interface{}, id string) error { func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
t := rType(bean) v := rValue(bean)
t := v.Type()
if t.Kind() != reflect.Struct { if t.Kind() != reflect.Struct {
return errors.New("error params") return errors.New("error params")
} }
table := engine.TableInfo(bean) tableName := engine.tbName(v)
table := engine.autoMapType(v)
cacher := table.Cacher cacher := table.Cacher
if cacher == nil { if cacher == nil {
cacher = engine.Cacher cacher = engine.Cacher
} }
if cacher != nil { if cacher != nil {
cacher.ClearIds(table.Name) cacher.ClearIds(tableName)
cacher.DelBean(table.Name, id) cacher.DelBean(tableName, id)
} }
return nil return nil
} }
@ -1266,18 +1253,20 @@ func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
// If enabled cache, clear some tables' cache // If enabled cache, clear some tables' cache
func (engine *Engine) ClearCache(beans ...interface{}) error { func (engine *Engine) ClearCache(beans ...interface{}) error {
for _, bean := range beans { for _, bean := range beans {
t := rType(bean) v := rValue(bean)
t := v.Type()
if t.Kind() != reflect.Struct { if t.Kind() != reflect.Struct {
return errors.New("error params") return errors.New("error params")
} }
table := engine.TableInfo(bean) tableName := engine.tbName(v)
table := engine.autoMapType(v)
cacher := table.Cacher cacher := table.Cacher
if cacher == nil { if cacher == nil {
cacher = engine.Cacher cacher = engine.Cacher
} }
if cacher != nil { if cacher != nil {
cacher.ClearIds(table.Name) cacher.ClearIds(tableName)
cacher.ClearBeans(table.Name) cacher.ClearBeans(tableName)
} }
} }
return nil return nil
@ -1288,11 +1277,13 @@ func (engine *Engine) ClearCache(beans ...interface{}) error {
// If you change some field, you should change the database manually. // If you change some field, you should change the database manually.
func (engine *Engine) Sync(beans ...interface{}) error { func (engine *Engine) Sync(beans ...interface{}) error {
for _, bean := range beans { for _, bean := range beans {
table := engine.TableInfo(bean) v := rValue(bean)
tableName := engine.tbName(v)
table := engine.autoMapType(v)
s := engine.NewSession() s := engine.NewSession()
defer s.Close() defer s.Close()
isExist, err := s.Table(bean).isTableExist(table.Name) isExist, err := s.Table(bean).isTableExist(tableName)
if err != nil { if err != nil {
return err return err
} }
@ -1306,7 +1297,7 @@ func (engine *Engine) Sync(beans ...interface{}) error {
if err != nil { if err != nil {
return err return err
}*/ }*/
var isEmpty bool = false var isEmpty bool
if isEmpty { if isEmpty {
err = engine.DropTables(bean) err = engine.DropTables(bean)
if err != nil { if err != nil {
@ -1321,7 +1312,7 @@ func (engine *Engine) Sync(beans ...interface{}) error {
session := engine.NewSession() session := engine.NewSession()
session.Statement.RefTable = table session.Statement.RefTable = table
defer session.Close() defer session.Close()
isExist, err := session.Engine.dialect.IsColumnExist(table.Name, col.Name) isExist, err := session.Engine.dialect.IsColumnExist(tableName, col.Name)
if err != nil { if err != nil {
return err return err
} }
@ -1342,7 +1333,7 @@ func (engine *Engine) Sync(beans ...interface{}) error {
defer session.Close() defer session.Close()
if index.Type == core.UniqueType { if index.Type == core.UniqueType {
//isExist, err := session.isIndexExist(table.Name, name, true) //isExist, err := session.isIndexExist(table.Name, name, true)
isExist, err := session.isIndexExist2(table.Name, index.Cols, true) isExist, err := session.isIndexExist2(tableName, index.Cols, true)
if err != nil { if err != nil {
return err return err
} }
@ -1350,13 +1341,13 @@ func (engine *Engine) Sync(beans ...interface{}) error {
session := engine.NewSession() session := engine.NewSession()
session.Statement.RefTable = table session.Statement.RefTable = table
defer session.Close() defer session.Close()
err = session.addUnique(engine.tbName(table), name) err = session.addUnique(tableName, name)
if err != nil { if err != nil {
return err return err
} }
} }
} else if index.Type == core.IndexType { } else if index.Type == core.IndexType {
isExist, err := session.isIndexExist2(table.Name, index.Cols, false) isExist, err := session.isIndexExist2(tableName, index.Cols, false)
if err != nil { if err != nil {
return err return err
} }
@ -1364,7 +1355,7 @@ func (engine *Engine) Sync(beans ...interface{}) error {
session := engine.NewSession() session := engine.NewSession()
session.Statement.RefTable = table session.Statement.RefTable = table
defer session.Close() defer session.Close()
err = session.addIndex(engine.tbName(table), name) err = session.addIndex(tableName, name)
if err != nil { if err != nil {
return err return err
} }
@ -1416,8 +1407,9 @@ func (engine *Engine) dropAll() error {
// CreateTables create tabls according bean // CreateTables create tabls according bean
func (engine *Engine) CreateTables(beans ...interface{}) error { func (engine *Engine) CreateTables(beans ...interface{}) error {
session := engine.NewSession() session := engine.NewSession()
err := session.Begin()
defer session.Close() defer session.Close()
err := session.Begin()
if err != nil { if err != nil {
return err return err
} }

View File

@ -29,11 +29,13 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
rows.session = session rows.session = session
rows.beanType = reflect.Indirect(reflect.ValueOf(bean)).Type() rows.beanType = reflect.Indirect(reflect.ValueOf(bean)).Type()
defer rows.session.Statement.Init() defer rows.session.resetStatement()
var sqlStr string var sqlStr string
var args []interface{} var args []interface{}
rows.session.Statement.RefTable = rows.session.Engine.TableInfo(bean)
rows.session.Statement.setRefValue(rValue(bean))
if rows.session.Statement.RawSQL == "" { if rows.session.Statement.RawSQL == "" {
sqlStr, args = rows.session.Statement.genGetSql(bean) sqlStr, args = rows.session.Statement.genGetSql(bean)
} else { } else {

View File

@ -444,7 +444,9 @@ func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]b
} }
var col *core.Column var col *core.Column
table := session.Engine.autoMapType(dataStruct) session.Statement.setRefValue(dataStruct)
table := session.Statement.RefTable
tableName := session.Statement.tableName
for key, data := range objMap { for key, data := range objMap {
if col = table.GetColumn(key); col == nil { if col = table.GetColumn(key); col == nil {
@ -468,7 +470,7 @@ func (session *Session) scanMapIntoStruct(obj interface{}, objMap map[string][]b
fieldValue = dataStruct.FieldByName(fieldName) fieldValue = dataStruct.FieldByName(fieldName)
} }
if !fieldValue.IsValid() || !fieldValue.CanSet() { if !fieldValue.IsValid() || !fieldValue.CanSet() {
session.Engine.logger.Warnf("table %v's column %v is not valid or cannot set", table.Name, key) session.Engine.logger.Warnf("table %v's column %v is not valid or cannot set", tableName, key)
continue continue
} }
@ -534,7 +536,7 @@ func (session *Session) Exec(sqlStr string, args ...interface{}) (sql.Result, er
// CreateTable create a table according a bean // CreateTable create a table according a bean
func (session *Session) CreateTable(bean interface{}) error { func (session *Session) CreateTable(bean interface{}) error {
v := rValue(bean) v := rValue(bean)
session.Statement.RefTable = session.Engine.mapType(v) session.Statement.setRefValue(v)
defer session.resetStatement() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
@ -547,7 +549,7 @@ func (session *Session) CreateTable(bean interface{}) error {
// CreateIndexes create indexes // CreateIndexes create indexes
func (session *Session) CreateIndexes(bean interface{}) error { func (session *Session) CreateIndexes(bean interface{}) error {
v := rValue(bean) v := rValue(bean)
session.Statement.RefTable = session.Engine.mapType(v) session.Statement.setRefValue(v)
defer session.resetStatement() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
@ -567,7 +569,7 @@ func (session *Session) CreateIndexes(bean interface{}) error {
// CreateUniques create uniques // CreateUniques create uniques
func (session *Session) CreateUniques(bean interface{}) error { func (session *Session) CreateUniques(bean interface{}) error {
v := rValue(bean) v := rValue(bean)
session.Statement.RefTable = session.Engine.mapType(v) session.Statement.setRefValue(v)
defer session.resetStatement() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
@ -592,14 +594,15 @@ func (session *Session) createOneTable() error {
// to be deleted // to be deleted
func (session *Session) createAll() error { func (session *Session) createAll() error {
defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
for _, table := range session.Engine.Tables { for _, table := range session.Engine.Tables {
session.Statement.RefTable = table session.Statement.RefTable = table
session.Statement.tableName = table.Name
err := session.createOneTable() err := session.createOneTable()
session.resetStatement()
if err != nil { if err != nil {
return err return err
} }
@ -609,6 +612,9 @@ func (session *Session) createAll() error {
// drop indexes // drop indexes
func (session *Session) DropIndexes(bean interface{}) error { func (session *Session) DropIndexes(bean interface{}) error {
v := rValue(bean)
session.Statement.setRefValue(v)
defer session.resetStatement() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
@ -775,9 +781,11 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
return ErrCacheFailed return ErrCacheFailed
} }
tableName := session.Statement.TableName()
table := session.Statement.RefTable table := session.Statement.RefTable
cacher := session.Engine.getCacher2(table) cacher := session.Engine.getCacher2(table)
ids, err := core.GetCacheSql(cacher, session.Statement.TableName(), newsql, args) ids, err := core.GetCacheSql(cacher, tableName, newsql, args)
if err != nil { if err != nil {
rows, err := session.DB().Query(newsql, args...) rows, err := session.DB().Query(newsql, args...)
if err != nil { if err != nil {
@ -817,8 +825,6 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
ids = append(ids, pk) ids = append(ids, pk)
} }
tableName := session.Statement.TableName()
session.Engine.logger.Debug("[cacheFind] cache sql:", ids, tableName, newsql, args) session.Engine.logger.Debug("[cacheFind] cache sql:", ids, tableName, newsql, args)
err = core.PutCacheSql(cacher, ids, tableName, newsql, args) err = core.PutCacheSql(cacher, ids, tableName, newsql, args)
if err != nil { if err != nil {
@ -833,7 +839,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
ididxes := make(map[string]int) ididxes := make(map[string]int)
var ides []core.PK = make([]core.PK, 0) var ides []core.PK = make([]core.PK, 0)
var temps []interface{} = make([]interface{}, len(ids)) var temps []interface{} = make([]interface{}, len(ids))
tableName := session.Statement.TableName()
for idx, id := range ids { for idx, id := range ids {
sid, err := id.ToString() sid, err := id.ToString()
if err != nil { if err != nil {
@ -1007,14 +1013,12 @@ func (session *Session) Get(bean interface{}) (bool, error) {
defer session.Close() defer session.Close()
} }
session.Statement.setRefValue(rValue(bean))
session.Statement.Limit(1) session.Statement.Limit(1)
var sqlStr string var sqlStr string
var args []interface{} var args []interface{}
if session.Statement.RefTable == nil {
session.Statement.RefTable = session.Engine.TableInfo(bean)
}
if session.Statement.RawSQL == "" { if session.Statement.RawSQL == "" {
sqlStr, args = session.Statement.genGetSql(bean) sqlStr, args = session.Statement.genGetSql(bean)
} else { } else {
@ -1199,26 +1203,25 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
} }
sliceElementType := sliceValue.Type().Elem() sliceElementType := sliceValue.Type().Elem()
var table *core.Table
if session.Statement.RefTable == nil { if session.Statement.RefTable == nil {
if sliceElementType.Kind() == reflect.Ptr { if sliceElementType.Kind() == reflect.Ptr {
if sliceElementType.Elem().Kind() == reflect.Struct { if sliceElementType.Elem().Kind() == reflect.Struct {
pv := reflect.New(sliceElementType.Elem()) pv := reflect.New(sliceElementType.Elem())
table = session.Engine.autoMapType(pv.Elem()) session.Statement.setRefValue(pv.Elem())
} else { } else {
return errors.New("slice type") return errors.New("slice type")
} }
} else if sliceElementType.Kind() == reflect.Struct { } else if sliceElementType.Kind() == reflect.Struct {
pv := reflect.New(sliceElementType) pv := reflect.New(sliceElementType)
table = session.Engine.autoMapType(pv.Elem()) session.Statement.setRefValue(pv.Elem())
} else { } else {
return errors.New("slice type") return errors.New("slice type")
} }
session.Statement.RefTable = table
} else {
table = session.Statement.RefTable
} }
var table = session.Statement.RefTable
var addedTableName = (len(session.Statement.JoinStr) > 0) var addedTableName = (len(session.Statement.JoinStr) > 0)
if !session.Statement.noAutoCondition && len(condiBean) > 0 { if !session.Statement.noAutoCondition && len(condiBean) > 0 {
colNames, args := session.Statement.buildConditions(table, condiBean[0], true, true, false, true, addedTableName) colNames, args := session.Statement.buildConditions(table, condiBean[0], true, true, false, true, addedTableName)
@ -1412,17 +1415,6 @@ func (session *Session) Ping() error {
return session.DB().Ping() return session.DB().Ping()
} }
func (engine *Engine) tableName(beanOrTableName interface{}) (string, error) {
v := rValue(beanOrTableName)
if v.Type().Kind() == reflect.String {
return beanOrTableName.(string), nil
} else if v.Type().Kind() == reflect.Struct {
table := engine.autoMapType(v)
return table.Name, nil
}
return "", errors.New("bean should be a struct or struct's point")
}
// IsTableExist if a table is exist // IsTableExist if a table is exist
func (session *Session) IsTableExist(beanOrTableName interface{}) (bool, error) { func (session *Session) IsTableExist(beanOrTableName interface{}) (bool, error) {
tableName, err := session.Engine.tableName(beanOrTableName) tableName, err := session.Engine.tableName(beanOrTableName)
@ -1451,7 +1443,6 @@ func (session *Session) IsTableEmpty(bean interface{}) (bool, error) {
if t.Kind() == reflect.String { if t.Kind() == reflect.String {
return session.isTableEmpty(bean.(string)) return session.isTableEmpty(bean.(string))
} else if t.Kind() == reflect.Struct { } else if t.Kind() == reflect.Struct {
session.Engine.autoMapType(v)
rows, err := session.Count(bean) rows, err := session.Count(bean)
return rows == 0, err return rows == 0, err
} }
@ -1614,8 +1605,9 @@ func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount i
return errors.New("Expected a pointer to a struct") return errors.New("Expected a pointer to a struct")
} }
table := session.Engine.autoMapType(dataStruct) session.Statement.setRefValue(dataStruct)
return session._row2Bean(rows, fields, fieldsCount, bean, &dataStruct, table)
return session._row2Bean(rows, fields, fieldsCount, bean, &dataStruct, session.Statement.RefTable)
} }
func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}, dataStruct *reflect.Value, table *core.Table) error { func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount int, bean interface{}, dataStruct *reflect.Value, table *core.Table) error {
@ -2177,7 +2169,7 @@ func (session *Session) query2(sqlStr string, paramStr ...interface{}) (resultsS
func (session *Session) Insert(beans ...interface{}) (int64, error) { func (session *Session) Insert(beans ...interface{}) (int64, error) {
var affected int64 var affected int64
var err error var err error
defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -2189,6 +2181,7 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) {
if size > 0 { if size > 0 {
if session.Engine.SupportInsertMany() { if session.Engine.SupportInsertMany() {
cnt, err := session.innerInsertMulti(bean) cnt, err := session.innerInsertMulti(bean)
session.resetStatement()
if err != nil { if err != nil {
return affected, err return affected, err
} }
@ -2196,6 +2189,7 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) {
} else { } else {
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
cnt, err := session.innerInsert(sliceValue.Index(i).Interface()) cnt, err := session.innerInsert(sliceValue.Index(i).Interface())
session.resetStatement()
if err != nil { if err != nil {
return affected, err return affected, err
} }
@ -2205,6 +2199,7 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) {
} }
} else { } else {
cnt, err := session.innerInsert(bean) cnt, err := session.innerInsert(bean)
session.resetStatement()
if err != nil { if err != nil {
return affected, err return affected, err
} }
@ -2223,23 +2218,20 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
bean := sliceValue.Index(0).Interface() bean := sliceValue.Index(0).Interface()
elementValue := rValue(bean) elementValue := rValue(bean)
//sliceElementType := elementValue.Type() session.Statement.setRefValue(elementValue)
table := session.Statement.RefTable
table := session.Engine.autoMapType(elementValue)
session.Statement.RefTable = table
size := sliceValue.Len() size := sliceValue.Len()
colNames := make([]string, 0) var colNames []string
colMultiPlaces := make([]string, 0) var colMultiPlaces []string
var args = make([]interface{}, 0) var args []interface{}
cols := make([]*core.Column, 0) var cols []*core.Column
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
v := sliceValue.Index(i) v := sliceValue.Index(i)
vv := reflect.Indirect(v) vv := reflect.Indirect(v)
elemValue := v.Interface() elemValue := v.Interface()
colPlaces := make([]string, 0) var colPlaces []string
// handle BeforeInsertProcessor // handle BeforeInsertProcessor
// !nashtsai! does user expect it's same slice to passed closure when using Before()/After() when insert multi?? // !nashtsai! does user expect it's same slice to passed closure when using Before()/After() when insert multi??
@ -3063,8 +3055,8 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val
} }
func (session *Session) innerInsert(bean interface{}) (int64, error) { func (session *Session) innerInsert(bean interface{}) (int64, error) {
table := session.Engine.TableInfo(bean) session.Statement.setRefValue(rValue(bean))
session.Statement.RefTable = table table := session.Statement.RefTable
// handle BeforeInsertProcessor // handle BeforeInsertProcessor
for _, closure := range session.beforeClosures { for _, closure := range session.beforeClosures {
@ -3076,7 +3068,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
processor.BeforeInsert() processor.BeforeInsert()
} }
// -- // --
colNames, args, err := genCols(table, session, bean, false, false) colNames, args, err := genCols(session.Statement.RefTable, session, bean, false, false)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -3439,11 +3431,11 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
defer session.Close() defer session.Close()
} }
t := rType(bean) v := rValue(bean)
t := v.Type()
var colNames []string var colNames []string
var args []interface{} var args []interface{}
var table *core.Table
// handle before update processors // handle before update processors
for _, closure := range session.beforeClosures { for _, closure := range session.beforeClosures {
@ -3459,25 +3451,25 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
var isMap = t.Kind() == reflect.Map var isMap = t.Kind() == reflect.Map
var isStruct = t.Kind() == reflect.Struct var isStruct = t.Kind() == reflect.Struct
if isStruct { if isStruct {
table = session.Engine.TableInfo(bean) session.Statement.setRefValue(v)
session.Statement.RefTable = table
if session.Statement.ColumnStr == "" { if session.Statement.ColumnStr == "" {
colNames, args = buildUpdates(session.Engine, table, bean, false, false, colNames, args = buildUpdates(session.Engine, session.Statement.RefTable, bean, false, false,
false, false, session.Statement.allUseBool, session.Statement.useAllCols, false, false, session.Statement.allUseBool, session.Statement.useAllCols,
session.Statement.mustColumnMap, session.Statement.nullableMap, session.Statement.mustColumnMap, session.Statement.nullableMap,
session.Statement.columnMap, true, session.Statement.unscoped) session.Statement.columnMap, true, session.Statement.unscoped)
} else { } else {
colNames, args, err = genCols(table, session, bean, true, true) colNames, args, err = genCols(session.Statement.RefTable, session, bean, true, true)
if err != nil { if err != nil {
return 0, err return 0, err
} }
} }
} else if isMap { } else if isMap {
// TODO: So why Table("table_name") could not be used with update map?
if session.Statement.RefTable == nil { if session.Statement.RefTable == nil {
return 0, ErrTableNotFound return 0, ErrTableNotFound
} }
table = session.Statement.RefTable
colNames = make([]string, 0) colNames = make([]string, 0)
args = make([]interface{}, 0) args = make([]interface{}, 0)
bValue := reflect.Indirect(reflect.ValueOf(bean)) bValue := reflect.Indirect(reflect.ValueOf(bean))
@ -3490,6 +3482,8 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
return 0, ErrParamsType return 0, ErrParamsType
} }
table := session.Statement.RefTable
if session.Statement.UseAutoTime && table.Updated != "" { if session.Statement.UseAutoTime && table.Updated != "" {
colNames = append(colNames, session.Engine.Quote(table.Updated)+" = ?") colNames = append(colNames, session.Engine.Quote(table.Updated)+" = ?")
col := table.UpdatedColumn() col := table.UpdatedColumn()
@ -3691,18 +3685,16 @@ func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error {
for _, col := range session.Statement.RefTable.PKColumns() { for _, col := range session.Statement.RefTable.PKColumns() {
if v, ok := data[col.Name]; !ok { if v, ok := data[col.Name]; !ok {
return errors.New("no id") return errors.New("no id")
} else { } else if col.SQLType.IsText() {
if col.SQLType.IsText() { pk = append(pk, string(v))
pk = append(pk, string(v)) } else if col.SQLType.IsNumeric() {
} else if col.SQLType.IsNumeric() { id, err = strconv.ParseInt(string(v), 10, 64)
id, err = strconv.ParseInt(string(v), 10, 64) if err != nil {
if err != nil { return err
return err
}
pk = append(pk, id)
} else {
return errors.New("not supported primary key type")
} }
pk = append(pk, id)
} else {
return errors.New("not supported primary key type")
} }
} }
ids = append(ids, pk) ids = append(ids, pk)
@ -3733,6 +3725,9 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
defer session.Close() defer session.Close()
} }
session.Statement.setRefValue(rValue(bean))
var table = session.Statement.RefTable
// handle before delete processors // handle before delete processors
for _, closure := range session.beforeClosures { for _, closure := range session.beforeClosures {
closure(bean) closure(bean)
@ -3744,8 +3739,6 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
} }
// -- // --
table := session.Engine.TableInfo(bean)
session.Statement.RefTable = table
var colNames []string var colNames []string
var args []interface{} var args []interface{}
@ -3925,19 +3918,6 @@ func (session *Session) LastSQL() (string, []interface{}) {
return session.lastSQL, session.lastSQLArgs return session.lastSQL, session.lastSQLArgs
} }
// tbName get some table's table name
func (session *Session) tbName(table *core.Table) string {
var tbName = table.Name
if len(session.Statement.AltTableName) > 0 {
tbName = session.Statement.AltTableName
}
/*if len(session.Engine.dialect.URI().Schema) > 0 {
return session.Engine.dialect.URI().Schema + "." + tbName
}*/
return tbName
}
// tbName get some table's table name // tbName get some table's table name
func (session *Session) tbNameNoSchema(table *core.Table) string { func (session *Session) tbNameNoSchema(table *core.Table) string {
if len(session.Statement.AltTableName) > 0 { if len(session.Statement.AltTableName) > 0 {
@ -4008,7 +3988,7 @@ func (s *Session) Sync2(beans ...interface{}) error {
engine.dialect.DBType() == core.POSTGRES { engine.dialect.DBType() == core.POSTGRES {
engine.logger.Infof("Table %s column %s change type from %s to %s\n", engine.logger.Infof("Table %s column %s change type from %s to %s\n",
tbName, col.Name, curType, expectedType) tbName, col.Name, curType, expectedType)
_, err = engine.Exec(engine.dialect.ModifyColumnSql(engine.tbName(table), col)) _, err = engine.Exec(engine.dialect.ModifyColumnSql(table.Name, col))
} else { } else {
engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s\n", engine.logger.Warnf("Table %s column %s db type is %s, struct type is %s\n",
tbName, col.Name, curType, expectedType) tbName, col.Name, curType, expectedType)
@ -4018,7 +3998,7 @@ func (s *Session) Sync2(beans ...interface{}) error {
if oriCol.Length < col.Length { if oriCol.Length < col.Length {
engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n", engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
tbName, col.Name, oriCol.Length, col.Length) tbName, col.Name, oriCol.Length, col.Length)
_, err = engine.Exec(engine.dialect.ModifyColumnSql(engine.tbName(table), col)) _, err = engine.Exec(engine.dialect.ModifyColumnSql(table.Name, col))
} }
} }
} else { } else {
@ -4032,7 +4012,7 @@ func (s *Session) Sync2(beans ...interface{}) error {
if oriCol.Length < col.Length { if oriCol.Length < col.Length {
engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n", engine.logger.Infof("Table %s column %s change type from varchar(%d) to varchar(%d)\n",
tbName, col.Name, oriCol.Length, col.Length) tbName, col.Name, oriCol.Length, col.Length)
_, err = engine.Exec(engine.dialect.ModifyColumnSql(engine.tbName(table), col)) _, err = engine.Exec(engine.dialect.ModifyColumnSql(table.Name, col))
} }
} }
} }

View File

@ -58,6 +58,7 @@ type Statement struct {
OmitStr string OmitStr string
ConditionStr string ConditionStr string
AltTableName string AltTableName string
tableName string
RawSQL string RawSQL string
RawParams []interface{} RawParams []interface{}
UseCascade bool UseCascade bool
@ -100,6 +101,7 @@ func (statement *Statement) Init() {
statement.columnMap = make(map[string]bool) statement.columnMap = make(map[string]bool)
statement.ConditionStr = "" statement.ConditionStr = ""
statement.AltTableName = "" statement.AltTableName = ""
statement.tableName = ""
statement.IdParam = nil statement.IdParam = nil
statement.RawSQL = "" statement.RawSQL = ""
statement.RawParams = make([]interface{}, 0) statement.RawParams = make([]interface{}, 0)
@ -188,6 +190,11 @@ func (statement *Statement) Or(querystring string, args ...interface{}) *Stateme
return statement return statement
} }
func (statement *Statement) setRefValue(v reflect.Value) {
statement.RefTable = statement.Engine.autoMapType(v)
statement.tableName = statement.Engine.tbName(v)
}
// Table tempororily set table name, the parameter could be a string or a pointer of struct // Table tempororily set table name, the parameter could be a string or a pointer of struct
func (statement *Statement) Table(tableNameOrBean interface{}) *Statement { func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
v := rValue(tableNameOrBean) v := rValue(tableNameOrBean)
@ -196,6 +203,7 @@ func (statement *Statement) Table(tableNameOrBean interface{}) *Statement {
statement.AltTableName = tableNameOrBean.(string) statement.AltTableName = tableNameOrBean.(string)
} else if t.Kind() == reflect.Struct { } else if t.Kind() == reflect.Struct {
statement.RefTable = statement.Engine.autoMapType(v) statement.RefTable = statement.Engine.autoMapType(v)
statement.AltTableName = statement.Engine.tbName(v)
} }
return statement return statement
} }
@ -678,14 +686,7 @@ func (statement *Statement) TableName() string {
return statement.AltTableName return statement.AltTableName
} }
if statement.RefTable != nil { return statement.tableName
/*schema := statement.Engine.dialect.URI().Schema
if len(schema) > 0 {
return schema + "." + statement.RefTable.Name
}*/
return statement.RefTable.Name
}
return ""
} }
// Id generate "where id = ? " statment or for composite key "where key1 = ? and key2 = ?" // Id generate "where id = ? " statment or for composite key "where key1 = ? and key2 = ?"
@ -998,8 +999,7 @@ func (statement *Statement) Join(joinOP string, tablename interface{}, condition
if t.Kind() == reflect.String { if t.Kind() == reflect.String {
table = f.(string) table = f.(string)
} else if t.Kind() == reflect.Struct { } else if t.Kind() == reflect.Struct {
r := statement.Engine.autoMapType(v) table = statement.Engine.tbName(v)
table = r.Name
} }
} }
if l > 1 { if l > 1 {
@ -1038,7 +1038,7 @@ func (statement *Statement) Unscoped() *Statement {
func (statement *Statement) genColumnStr() string { func (statement *Statement) genColumnStr() string {
table := statement.RefTable table := statement.RefTable
colNames := make([]string, 0) var colNames []string
for _, col := range table.Columns() { for _, col := range table.Columns() {
if statement.OmitStr != "" { if statement.OmitStr != "" {
if _, ok := statement.columnMap[strings.ToLower(col.Name)]; ok { if _, ok := statement.columnMap[strings.ToLower(col.Name)]; ok {
@ -1075,17 +1075,17 @@ func (statement *Statement) genColumnStr() string {
} }
func (statement *Statement) genCreateTableSQL() string { func (statement *Statement) genCreateTableSQL() string {
return statement.Engine.dialect.CreateTableSql(statement.RefTable, statement.AltTableName, return statement.Engine.dialect.CreateTableSql(statement.RefTable, statement.TableName(),
statement.StoreEngine, statement.Charset) statement.StoreEngine, statement.Charset)
} }
func (s *Statement) genIndexSQL() []string { func (s *Statement) genIndexSQL() []string {
var sqls []string = make([]string, 0) var sqls []string
tbName := s.TableName() tbName := s.TableName()
quote := s.Engine.Quote quote := s.Engine.Quote
for idxName, index := range s.RefTable.Indexes { for idxName, index := range s.RefTable.Indexes {
if index.Type == core.IndexType { if index.Type == core.IndexType {
sql := fmt.Sprintf("CREATE INDEX %v ON %v (%v);", quote(indexName(s.RefTable.Name, idxName)), sql := fmt.Sprintf("CREATE INDEX %v ON %v (%v);", quote(indexName(tbName, idxName)),
quote(tbName), quote(strings.Join(index.Cols, quote(",")))) quote(tbName), quote(strings.Join(index.Cols, quote(","))))
sqls = append(sqls, sql) sqls = append(sqls, sql)
} }
@ -1098,10 +1098,11 @@ func uniqueName(tableName, uqeName string) string {
} }
func (s *Statement) genUniqueSQL() []string { func (s *Statement) genUniqueSQL() []string {
var sqls []string = make([]string, 0) var sqls []string
tbName := s.TableName()
for _, index := range s.RefTable.Indexes { for _, index := range s.RefTable.Indexes {
if index.Type == core.UniqueType { if index.Type == core.UniqueType {
sql := s.Engine.dialect.CreateIndexSql(s.RefTable.Name, index) sql := s.Engine.dialect.CreateIndexSql(tbName, index)
sqls = append(sqls, sql) sqls = append(sqls, sql)
} }
} }
@ -1109,13 +1110,14 @@ func (s *Statement) genUniqueSQL() []string {
} }
func (s *Statement) genDelIndexSQL() []string { func (s *Statement) genDelIndexSQL() []string {
var sqls []string = make([]string, 0) var sqls []string
tbName := s.TableName()
for idxName, index := range s.RefTable.Indexes { for idxName, index := range s.RefTable.Indexes {
var rIdxName string var rIdxName string
if index.Type == core.UniqueType { if index.Type == core.UniqueType {
rIdxName = uniqueName(s.RefTable.Name, idxName) rIdxName = uniqueName(tbName, idxName)
} else if index.Type == core.IndexType { } else if index.Type == core.IndexType {
rIdxName = indexName(s.RefTable.Name, idxName) rIdxName = indexName(tbName, idxName)
} }
sql := fmt.Sprintf("DROP INDEX %v", s.Engine.Quote(rIdxName)) sql := fmt.Sprintf("DROP INDEX %v", s.Engine.Quote(rIdxName))
if s.Engine.dialect.IndexOnTable() { if s.Engine.dialect.IndexOnTable() {
@ -1127,14 +1129,9 @@ func (s *Statement) genDelIndexSQL() []string {
} }
func (statement *Statement) genGetSql(bean interface{}) (string, []interface{}) { func (statement *Statement) genGetSql(bean interface{}) (string, []interface{}) {
var table *core.Table statement.setRefValue(rValue(bean))
if statement.RefTable == nil {
table = statement.Engine.TableInfo(bean)
statement.RefTable = table
} else {
table = statement.RefTable
}
var table = statement.RefTable
var addedTableName = (len(statement.JoinStr) > 0) var addedTableName = (len(statement.JoinStr) > 0)
if !statement.noAutoCondition { if !statement.noAutoCondition {
@ -1144,7 +1141,7 @@ func (statement *Statement) genGetSql(bean interface{}) (string, []interface{})
statement.BeanArgs = args statement.BeanArgs = args
} }
var columnStr string = statement.ColumnStr var columnStr = statement.ColumnStr
if len(statement.selectStr) > 0 { if len(statement.selectStr) > 0 {
columnStr = statement.selectStr columnStr = statement.selectStr
} else { } else {
@ -1199,13 +1196,12 @@ func (statement *Statement) buildConditions(table *core.Table, bean interface{},
} }
func (statement *Statement) genCountSql(bean interface{}) (string, []interface{}) { func (statement *Statement) genCountSql(bean interface{}) (string, []interface{}) {
table := statement.Engine.TableInfo(bean) statement.setRefValue(rValue(bean))
statement.RefTable = table
var addedTableName = (len(statement.JoinStr) > 0) var addedTableName = (len(statement.JoinStr) > 0)
if !statement.noAutoCondition { if !statement.noAutoCondition {
colNames, args := statement.buildConditions(table, bean, true, true, false, true, addedTableName) colNames, args := statement.buildConditions(statement.RefTable, bean, true, true, false, true, addedTableName)
statement.ConditionStr = strings.Join(colNames, " "+statement.Engine.Dialect().AndStr()+" ") statement.ConditionStr = strings.Join(colNames, " "+statement.Engine.Dialect().AndStr()+" ")
statement.BeanArgs = args statement.BeanArgs = args
@ -1221,13 +1217,12 @@ func (statement *Statement) genCountSql(bean interface{}) (string, []interface{}
} }
func (statement *Statement) genSumSql(bean interface{}, columns ...string) (string, []interface{}) { func (statement *Statement) genSumSql(bean interface{}, columns ...string) (string, []interface{}) {
table := statement.Engine.TableInfo(bean) statement.setRefValue(rValue(bean))
statement.RefTable = table
var addedTableName = (len(statement.JoinStr) > 0) var addedTableName = (len(statement.JoinStr) > 0)
if !statement.noAutoCondition { if !statement.noAutoCondition {
colNames, args := statement.buildConditions(table, bean, true, true, false, true, addedTableName) colNames, args := statement.buildConditions(statement.RefTable, bean, true, true, false, true, addedTableName)
statement.ConditionStr = strings.Join(colNames, " "+statement.Engine.Dialect().AndStr()+" ") statement.ConditionStr = strings.Join(colNames, " "+statement.Engine.Dialect().AndStr()+" ")
statement.BeanArgs = args statement.BeanArgs = args
@ -1269,7 +1264,7 @@ func (statement *Statement) genSelectSQL(columnStr string) (a string) {
} }
var whereStr = buf.String() var whereStr = buf.String()
var fromStr string = " FROM " + quote(statement.TableName()) var fromStr = " FROM " + quote(statement.TableName())
if statement.TableAlias != "" { if statement.TableAlias != "" {
if dialect.DBType() == core.ORACLE { if dialect.DBType() == core.ORACLE {
fromStr += " " + quote(statement.TableAlias) fromStr += " " + quote(statement.TableAlias)
@ -1286,7 +1281,7 @@ func (statement *Statement) genSelectSQL(columnStr string) (a string) {
top = fmt.Sprintf(" TOP %d ", statement.LimitN) top = fmt.Sprintf(" TOP %d ", statement.LimitN)
} }
if statement.Start > 0 { if statement.Start > 0 {
var column string = "(id)" var column = "(id)"
if len(statement.RefTable.PKColumns()) == 0 { if len(statement.RefTable.PKColumns()) == 0 {
for _, index := range statement.RefTable.Indexes { for _, index := range statement.RefTable.Indexes {
if len(index.Cols) == 1 { if len(index.Cols) == 1 {

View File

@ -17,7 +17,7 @@ import (
const ( const (
// Version show the xorm's version // Version show the xorm's version
Version string = "0.5.5.0707" Version string = "0.5.5.0709"
) )
func regDrvsNDialects() bool { func regDrvsNDialects() bool {