Merge remote-tracking branch 'origin/master' into feature/cacher-tag

This commit is contained in:
Nash Tsai 2014-06-20 21:56:46 +08:00
commit 2f121b9566
12 changed files with 379 additions and 129 deletions

View File

@ -1 +1 @@
xorm v0.4.0 RC1 xorm v0.4.0

View File

@ -4,7 +4,7 @@
新特性: 新特性:
* 移动xorm cmd [github.com/go-xorm/cmd](github.com/go-xorm/cmd) * 移动xorm cmd [github.com/go-xorm/cmd](github.com/go-xorm/cmd)
* 在重构一般DB操作核心库 [github.com/go-xorm/core](https://github.com/go-xorm/core) * 在重构一般DB操作核心库 [github.com/go-xorm/core](https://github.com/go-xorm/core)
* 移动测试github.com/复XORM/测试 [github.com/go-xorm/tests](github.com/go-xorm/tests) * 移动测试github.com/XORM/tests [github.com/go-xorm/tests](github.com/go-xorm/tests)
改进: 改进:
* Prepared statement 缓存 * Prepared statement 缓存

View File

@ -224,6 +224,8 @@ type Conversion interface {
} }
``` ```
- 5. If one struct has a Conversion field, so we need set an implementation to the field before get data from database. We can implement `BeforeSet(name string, cell xorm.Cell)` on struct to do this. For example: [testConversion](https://github.com/go-xorm/tests/blob/master/base.go#L1826)
<a name="30" id="30"></a> <a name="30" id="30"></a>
## 3. database meta information ## 3. database meta information
@ -510,7 +512,7 @@ total, err := engine.Where("id >?", 1).Count(user)
``` ```
<a name="70" id="70"></a> <a name="70" id="70"></a>
## 6.更新数据 ## 6.Update
更新数据使用`Update`方法Update方法的第一个参数为需要更新的内容可以为一个结构体指针或者一个Map[string]interface{}类型。当传入的为结构体指针时只有非空和0的field才会被作为更新的字段。当传入的为Map类型时key为数据库Column的名字value为要更新的内容。 更新数据使用`Update`方法Update方法的第一个参数为需要更新的内容可以为一个结构体指针或者一个Map[string]interface{}类型。当传入的为结构体指针时只有非空和0的field才会被作为更新的字段。当传入的为Map类型时key为数据库Column的名字value为要更新的内容。
@ -691,7 +693,7 @@ Please visit [https://github.com/go-xorm/xorm/tree/master/examples](https://gith
<a name="160"></a> <a name="160"></a>
## 15.FAQ ## 15.FAQ
1.How the xorm tag use both with json? * How the xorm tag use both with json?
Use space. Use space.
@ -700,3 +702,40 @@ type User struct {
Name string `json:"name" xorm:"name"` Name string `json:"name" xorm:"name"`
} }
``` ```
* Does xorm support composite primary key?
Yes. You can use pk tag. All fields have tag will as one primary key by fields order on struct. When use, you can use xorm.PK{1, 2}. For example: `Id(xorm.PK{1, 2})`.
* How to use join
We can use Join() and extends tag to do join operation. For example:
type Userinfo struct {
Id int64
Name string
DetailId int64
}
type Userdetail struct {
Id int64
Gender int
}
type User struct {
Userinfo `xorm:"extends"`
Userdetail `xorm:"extends"`
}
var users = make([]User, 0)
err := engine.Table(&Userinfo{}).Join("LEFT", "userdetail", "userinfo.detail_id = userdetail.id").Find(&users)
//assert(User.Userinfo.Id != 0 && User.Userdetail.Id != 0)
Please notice that Userinfo field on User should be before Userdetail because of the order on join SQL stsatement. If the order is wrong, the same name field may be set a wrong value.
Of course, If join statment is very long, you could directly use Sql():
err := engine.Sql("select * from userinfo, userdetail where userinfo.detail_id = userdetail.id").Find(&users)
//assert(User.Userinfo.Id != 0 && User.Userdetail.Id != 0)

View File

@ -224,6 +224,8 @@ type Conversion interface {
} }
``` ```
- 5.如果一个结构体包含一个Conversion的接口类型那么在获取数据时必须要预先设置一个实现此接口的struct或者struct的指针。此时可以在此struct中实现`BeforeSet(name string, cell xorm.Cell)`方法来进行预先给Conversion赋值。例子参见 [testConversion](https://github.com/go-xorm/tests/blob/master/base.go#L1826)
<a name="24" id="24"></a> <a name="24" id="24"></a>
### 2.4.Go与字段类型对应表 ### 2.4.Go与字段类型对应表
@ -828,6 +830,34 @@ money float64 `xorm:"Numeric"`
支持。在定义时如果有多个字段标记了pk则这些字段自动成为复合主键顺序为在struct中出现的顺序。在使用Id方法时可以用`Id(xorm.PK{1, 2})`的方式来用。 支持。在定义时如果有多个字段标记了pk则这些字段自动成为复合主键顺序为在struct中出现的顺序。在使用Id方法时可以用`Id(xorm.PK{1, 2})`的方式来用。
* xorm如何使用Join
一般我们配合Join()和extends标记来进行比如我们要对两个表进行Join操作我们可以这样
type Userinfo struct {
Id int64
Name string
DetailId int64
}
type Userdetail struct {
Id int64
Gender int
}
type User struct {
Userinfo `xorm:"extends"`
Userdetail `xorm:"extends"`
}
var users = make([]User, 0)
err := engine.Table(&Userinfo{}).Join("LEFT", "userdetail", "userinfo.detail_id = userdetail.id").Find(&users)
请注意这里的Userinfo在User中的位置必须在Userdetail的前面因为他在join语句中的顺序在userdetail前面。如果顺序不对那么对于同名的列有可能会赋值出错。
当然如果Join语句比较复杂我们也可以直接用Sql函数
err := engine.Sql("select * from userinfo, userdetail where userinfo.detail_id = userdetail.id").Find(&users)
<a name="170" id="170"></a> <a name="170" id="170"></a>
## 17.讨论 ## 17.讨论

178
engine.go
View File

@ -31,6 +31,7 @@ type Engine struct {
mutex *sync.RWMutex mutex *sync.RWMutex
Cacher core.Cacher Cacher core.Cacher
ShowInfo bool
ShowSQL bool ShowSQL bool
ShowErr bool ShowErr bool
ShowDebug bool ShowDebug bool
@ -141,8 +142,8 @@ func (engine *Engine) NoCascade() *Session {
// Set a table use a special cacher // Set a table use a special cacher
func (engine *Engine) MapCacher(bean interface{}, cacher core.Cacher) { func (engine *Engine) MapCacher(bean interface{}, cacher core.Cacher) {
v := rValue(bean) v := rValue(bean)
engine.autoMapType(v) tb := engine.autoMapType(v)
engine.Tables[v.Type()].Cacher = cacher tb.Cacher = cacher
} }
// NewDB provides an interface to operate database directly // NewDB provides an interface to operate database directly
@ -182,9 +183,9 @@ func (engine *Engine) Ping() error {
func (engine *Engine) logSQL(sqlStr string, sqlArgs ...interface{}) { func (engine *Engine) logSQL(sqlStr string, sqlArgs ...interface{}) {
if engine.ShowSQL { if engine.ShowSQL {
if len(sqlArgs) > 0 { if len(sqlArgs) > 0 {
engine.LogInfo("[sql]", sqlStr, "[args]", sqlArgs) engine.Logger.Info(fmt.Sprintln("[sql]", sqlStr, "[args]", sqlArgs))
} else { } else {
engine.LogInfo("[sql]", sqlStr) engine.Logger.Info(fmt.Sprintln("[sql]", sqlStr))
} }
} }
} }
@ -198,7 +199,9 @@ func (engine *Engine) LogError(contents ...interface{}) {
// logging error // logging error
func (engine *Engine) LogInfo(contents ...interface{}) { func (engine *Engine) LogInfo(contents ...interface{}) {
if engine.ShowInfo {
engine.Logger.Info(fmt.Sprintln(contents...)) engine.Logger.Info(fmt.Sprintln(contents...))
}
} }
// logging debug // logging debug
@ -333,10 +336,19 @@ func (engine *Engine) DumpAll(w io.Writer) error {
} else if col.SQLType.IsText() || col.SQLType.IsTime() { } else if col.SQLType.IsText() || col.SQLType.IsTime() {
var v = fmt.Sprintf("%s", d) var v = fmt.Sprintf("%s", d)
temp += ", '" + strings.Replace(v, "'", "''", -1) + "'" temp += ", '" + strings.Replace(v, "'", "''", -1) + "'"
} else if col.SQLType.IsBlob() /*reflect.TypeOf(d).Kind() == reflect.Slice*/ { } else if col.SQLType.IsBlob() /**/ {
if reflect.TypeOf(d).Kind() == reflect.Slice {
temp += fmt.Sprintf(", %s", engine.dialect.FormatBytes(d.([]byte))) temp += fmt.Sprintf(", %s", engine.dialect.FormatBytes(d.([]byte)))
} else if reflect.TypeOf(d).Kind() == reflect.String {
temp += fmt.Sprintf(", '%s'", d.(string))
}
} else { } else {
temp += fmt.Sprintf(", %s", d) s := fmt.Sprintf("%v", d)
if strings.Contains(s, ":") || strings.Contains(s, "-") {
temp += fmt.Sprintf(", '%s'", s)
} else {
temp += fmt.Sprintf(", %s", s)
}
} }
} }
_, err = io.WriteString(w, temp[2:]+");\n\n") _, err = io.WriteString(w, temp[2:]+");\n\n")
@ -479,7 +491,7 @@ func (engine *Engine) Desc(colNames ...string) *Session {
return session.Desc(colNames...) return session.Desc(colNames...)
} }
// Method Asc will generate "ORDER BY column1 DESC, column2 Asc" // Method Asc will generate "ORDER BY column1,column2 Asc"
// This method can chainable use. // This method can chainable use.
// //
// engine.Desc("name").Asc("age").Find(&users) // engine.Desc("name").Asc("age").Find(&users)
@ -614,6 +626,7 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
for i := 0; i < t.NumField(); i++ { for i := 0; i < t.NumField(); i++ {
tag := t.Field(i).Tag tag := t.Field(i).Tag
ormTagStr := tag.Get(engine.TagIdentifier) ormTagStr := tag.Get(engine.TagIdentifier)
if !hasProcessedCacheTag { if !hasProcessedCacheTag {
cacheTagStr := tag.Get("xorm_cache") cacheTagStr := tag.Get("xorm_cache")
@ -637,15 +650,10 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
continue continue
} }
if strings.ToUpper(tags[0]) == "EXTENDS" { if strings.ToUpper(tags[0]) == "EXTENDS" {
//fieldValue = reflect.Indirect(fieldValue)
//fmt.Println("----", fieldValue.Kind())
if fieldValue.Kind() == reflect.Struct { if fieldValue.Kind() == reflect.Struct {
//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", t.Field(i).Name, col.FieldName) col.FieldName = fmt.Sprintf("%v.%v", t.Field(i).Name, col.FieldName)
//fmt.Println("---", col.FieldName)
table.AddColumn(col) table.AddColumn(col)
} }
@ -657,7 +665,6 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
if !fieldValue.IsValid() || fieldValue.IsNil() { if !fieldValue.IsValid() || fieldValue.IsNil() {
fieldValue = reflect.New(f).Elem() fieldValue = reflect.New(f).Elem()
} }
//fmt.Println("00000", fieldValue)
} }
parentTable := engine.mapType(fieldValue) parentTable := engine.mapType(fieldValue)
@ -779,7 +786,7 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
if col.Length2 == 0 { if col.Length2 == 0 {
col.Length2 = col.SQLType.DefaultLength2 col.Length2 = col.SQLType.DefaultLength2
} }
//fmt.Println("======", col)
if col.Name == "" { if col.Name == "" {
col.Name = engine.ColumnMapper.Obj2Table(t.Field(i).Name) col.Name = engine.ColumnMapper.Obj2Table(t.Field(i).Name)
} }
@ -1053,6 +1060,138 @@ func (engine *Engine) Sync(beans ...interface{}) error {
return nil return nil
} }
func (engine *Engine) Sync2(beans ...interface{}) error {
tables, err := engine.DBMetas()
if err != nil {
return err
}
for _, bean := range beans {
table := engine.autoMap(bean)
var oriTable *core.Table
for _, tb := range tables {
if tb.Name == table.Name {
oriTable = tb
break
}
}
if oriTable == nil {
err = engine.CreateTables(bean)
if err != nil {
return err
}
err = engine.CreateUniques(bean)
if err != nil {
return err
}
err = engine.CreateIndexes(bean)
if err != nil {
return err
}
} else {
for _, col := range table.Columns() {
var oriCol *core.Column
for _, col2 := range oriTable.Columns() {
if col.Name == col2.Name {
oriCol = col2
break
}
}
if oriCol != nil {
if col.SQLType.Name != oriCol.SQLType.Name {
if col.SQLType.Name == core.Text &&
oriCol.SQLType.Name == core.Varchar {
// currently only support mysql
if engine.dialect.DBType() == core.MYSQL {
_, err = engine.Exec(engine.dialect.ModifyColumnSql(table.Name, col))
} else {
engine.LogWarn("Table %s Column %s Old data type is %s, new data type is %s",
table.Name, col.Name, oriCol.SQLType.Name, col.SQLType.Name)
}
} else {
engine.LogWarn("Table %s Column %s Old data type is %s, new data type is %s",
table.Name, col.Name, oriCol.SQLType.Name, col.SQLType.Name)
}
}
if col.Default != oriCol.Default {
engine.LogWarn("Table %s Column %s Old default is %s, new default is %s",
table.Name, col.Name, oriCol.Default, col.Default)
}
if col.Nullable != oriCol.Nullable {
engine.LogWarn("Table %s Column %s Old nullable is %v, new nullable is %v",
table.Name, col.Name, oriCol.Nullable, col.Nullable)
}
} else {
session := engine.NewSession()
session.Statement.RefTable = table
defer session.Close()
err = session.addColumn(col.Name)
}
if err != nil {
return err
}
}
var foundIndexNames = make(map[string]bool)
for name, index := range table.Indexes {
var oriIndex *core.Index
for name2, index2 := range oriTable.Indexes {
if index.Equal(index2) {
oriIndex = index2
foundIndexNames[name2] = true
break
}
}
if oriIndex != nil {
if oriIndex.Type != index.Type {
sql := engine.dialect.DropIndexSql(table.Name, oriIndex)
_, err = engine.Exec(sql)
if err != nil {
return err
}
oriIndex = nil
}
}
if oriIndex == nil {
if index.Type == core.UniqueType {
session := engine.NewSession()
session.Statement.RefTable = table
defer session.Close()
err = session.addUnique(table.Name, name)
} else if index.Type == core.IndexType {
session := engine.NewSession()
session.Statement.RefTable = table
defer session.Close()
err = session.addIndex(table.Name, name)
}
if err != nil {
return err
}
}
}
for name2, index2 := range oriTable.Indexes {
if _, ok := foundIndexNames[name2]; !ok {
sql := engine.dialect.DropIndexSql(table.Name, index2)
_, err = engine.Exec(sql)
if err != nil {
return err
}
}
}
}
}
return nil
}
func (engine *Engine) unMap(beans ...interface{}) (e error) { func (engine *Engine) unMap(beans ...interface{}) (e error) {
engine.mutex.Lock() engine.mutex.Lock()
defer engine.mutex.Unlock() defer engine.mutex.Unlock()
@ -1213,17 +1352,20 @@ func (engine *Engine) Count(bean interface{}) (int64, error) {
} }
// Import SQL DDL file // Import SQL DDL file
func (engine *Engine) Import(ddlPath string) ([]sql.Result, error) { func (engine *Engine) ImportFile(ddlPath string) ([]sql.Result, error) {
file, err := os.Open(ddlPath) file, err := os.Open(ddlPath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer file.Close() defer file.Close()
return engine.Import(file)
}
// Import SQL DDL file
func (engine *Engine) Import(r io.Reader) ([]sql.Result, error) {
var results []sql.Result var results []sql.Result
var lastError error var lastError error
scanner := bufio.NewScanner(file) scanner := bufio.NewScanner(r)
semiColSpliter := func(data []byte, atEOF bool) (advance int, token []byte, err error) { semiColSpliter := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 { if atEOF && len(data) == 0 {
@ -1244,7 +1386,7 @@ func (engine *Engine) Import(ddlPath string) ([]sql.Result, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
err = session.newDb() err := session.newDb()
if err != nil { if err != nil {
return results, err return results, err
} }

View File

@ -62,10 +62,10 @@ func (db *mssql) SqlType(c *core.Column) string {
var hasLen1 bool = (c.Length > 0) var hasLen1 bool = (c.Length > 0)
var hasLen2 bool = (c.Length2 > 0) var hasLen2 bool = (c.Length2 > 0)
if hasLen1 { if hasLen2 {
res += "(" + strconv.Itoa(c.Length) + ")"
} else if hasLen2 {
res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")" res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
} else if hasLen1 {
res += "(" + strconv.Itoa(c.Length) + ")"
} }
return res return res
} }

View File

@ -70,10 +70,11 @@ func (db *mysql) SqlType(c *core.Column) string {
var hasLen1 bool = (c.Length > 0) var hasLen1 bool = (c.Length > 0)
var hasLen2 bool = (c.Length2 > 0) var hasLen2 bool = (c.Length2 > 0)
if hasLen1 {
res += "(" + strconv.Itoa(c.Length) + ")" if hasLen2 {
} else if hasLen2 {
res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")" res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
} else if hasLen1 {
res += "(" + strconv.Itoa(c.Length) + ")"
} }
return res return res
} }

View File

@ -44,10 +44,10 @@ func (db *oracle) SqlType(c *core.Column) string {
var hasLen1 bool = (c.Length > 0) var hasLen1 bool = (c.Length > 0)
var hasLen2 bool = (c.Length2 > 0) var hasLen2 bool = (c.Length2 > 0)
if hasLen1 { if hasLen2 {
res += "(" + strconv.Itoa(c.Length) + ")"
} else if hasLen2 {
res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")" res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
} else if hasLen1 {
res += "(" + strconv.Itoa(c.Length) + ")"
} }
return res return res
} }

View File

@ -59,10 +59,10 @@ func (db *postgres) SqlType(c *core.Column) string {
var hasLen1 bool = (c.Length > 0) var hasLen1 bool = (c.Length > 0)
var hasLen2 bool = (c.Length2 > 0) var hasLen2 bool = (c.Length2 > 0)
if hasLen1 { if hasLen2 {
res += "(" + strconv.Itoa(c.Length) + ")"
} else if hasLen2 {
res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")" res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
} else if hasLen1 {
res += "(" + strconv.Itoa(c.Length) + ")"
} }
return res return res
} }
@ -108,10 +108,28 @@ func (db *postgres) TableCheckSql(tableName string) (string, []interface{}) {
" AND column_name = ?", args " AND column_name = ?", args
}*/ }*/
func (db *postgres) ModifyColumnSql(tableName string, col *core.Column) string {
return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s",
tableName, col.Name, db.SqlType(col))
}
func (db *postgres) DropIndexSql(tableName string, index *core.Index) string {
quote := db.Quote
//var unique string
var idxName string = index.Name
if !strings.HasPrefix(idxName, "UQE_") &&
!strings.HasPrefix(idxName, "IDX_") {
if index.Type == core.UniqueType {
idxName = fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
} else {
idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
}
}
return fmt.Sprintf("DROP INDEX %v", quote(idxName))
}
func (db *postgres) IsColumnExist(tableName string, col *core.Column) (bool, error) { func (db *postgres) IsColumnExist(tableName string, col *core.Column) (bool, error) {
args := []interface{}{tableName, col.Name} args := []interface{}{tableName, col.Name}
//query := "SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ?"
query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" + query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" +
" AND column_name = $2" " AND column_name = $2"
rows, err := db.DB().Query(query, args...) rows, err := db.DB().Query(query, args...)
@ -120,10 +138,7 @@ func (db *postgres) IsColumnExist(tableName string, col *core.Column) (bool, err
} }
defer rows.Close() defer rows.Close()
if rows.Next() { return rows.Next(), nil
return true, nil
}
return false, nil
} }
func (db *postgres) GetColumns(tableName string) ([]string, map[string]*core.Column, error) { func (db *postgres) GetColumns(tableName string) ([]string, map[string]*core.Column, error) {
@ -169,11 +184,7 @@ func (db *postgres) GetColumns(tableName string) ([]string, map[string]*core.Col
} }
} }
if isNullable == "YES" { col.Nullable = (isNullable == "YES")
col.Nullable = true
} else {
col.Nullable = false
}
switch dataType { switch dataType {
case "character varying", "character": case "character varying", "character":
@ -257,7 +268,9 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error)
return nil, err return nil, err
} }
indexName = strings.Trim(indexName, `" `) indexName = strings.Trim(indexName, `" `)
if strings.HasSuffix(indexName, "_pkey") {
continue
}
if strings.HasPrefix(indexdef, "CREATE UNIQUE INDEX") { if strings.HasPrefix(indexdef, "CREATE UNIQUE INDEX") {
indexType = core.UniqueType indexType = core.UniqueType
} else { } else {
@ -266,9 +279,6 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error)
cs := strings.Split(indexdef, "(") cs := strings.Split(indexdef, "(")
colNames = strings.Split(cs[1][0:len(cs[1])-1], ",") colNames = strings.Split(cs[1][0:len(cs[1])-1], ",")
if strings.HasSuffix(indexName, "_pkey") {
continue
}
if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) { if strings.HasPrefix(indexName, "IDX_"+tableName) || strings.HasPrefix(indexName, "UQE_"+tableName) {
newIdxName := indexName[5+len(tableName) : len(indexName)] newIdxName := indexName[5+len(tableName) : len(indexName)]
if newIdxName != "" { if newIdxName != "" {

View File

@ -26,6 +26,10 @@ type Session struct {
TransType string TransType string
IsAutoClose bool IsAutoClose bool
// Automatically reset the statement after operations that execute a SQL
// query such as Count(), Find(), Get(), ...
AutoResetStatement bool
// !nashtsai! storing these beans due to yet committed tx // !nashtsai! storing these beans due to yet committed tx
afterInsertBeans map[interface{}]*[]func(interface{}) afterInsertBeans map[interface{}]*[]func(interface{})
afterUpdateBeans map[interface{}]*[]func(interface{}) afterUpdateBeans map[interface{}]*[]func(interface{})
@ -45,6 +49,7 @@ func (session *Session) Init() {
session.IsAutoCommit = true session.IsAutoCommit = true
session.IsCommitedOrRollbacked = false session.IsCommitedOrRollbacked = false
session.IsAutoClose = false session.IsAutoClose = false
session.AutoResetStatement = true
// !nashtsai! is lazy init better? // !nashtsai! is lazy init better?
session.afterInsertBeans = make(map[interface{}]*[]func(interface{}), 0) session.afterInsertBeans = make(map[interface{}]*[]func(interface{}), 0)
@ -69,6 +74,12 @@ func (session *Session) Close() {
} }
} }
func (session *Session) resetStatement() {
if session.AutoResetStatement {
session.Statement.Init()
}
}
// Method Sql provides raw sql input parameter. When you have a complex SQL statement // Method Sql provides raw sql input parameter. When you have a complex SQL statement
// and cannot use Where, Id, In and etc. Methods to describe, you can use Sql. // and cannot use Where, Id, In and etc. Methods to describe, you can use Sql.
func (session *Session) Sql(querystring string, args ...interface{}) *Session { func (session *Session) Sql(querystring string, args ...interface{}) *Session {
@ -431,7 +442,7 @@ func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, er
sqlStr = filter.Do(sqlStr, session.Engine.dialect, session.Statement.RefTable) sqlStr = filter.Do(sqlStr, session.Engine.dialect, session.Statement.RefTable)
} }
session.Engine.logSQL(sqlStr, args) session.Engine.logSQL(sqlStr, args...)
if session.IsAutoCommit { if session.IsAutoCommit {
return session.innerExec(sqlStr, args...) return session.innerExec(sqlStr, args...)
@ -445,7 +456,7 @@ func (session *Session) Exec(sqlStr string, args ...interface{}) (sql.Result, er
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -461,7 +472,7 @@ func (session *Session) CreateTable(bean interface{}) error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -477,7 +488,7 @@ func (session *Session) CreateIndexes(bean interface{}) error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -500,7 +511,7 @@ func (session *Session) CreateUniques(bean interface{}) error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -528,7 +539,7 @@ func (session *Session) createAll() error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -549,7 +560,7 @@ func (session *Session) DropIndexes(bean interface{}) error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -571,13 +582,13 @@ func (session *Session) DropTable(bean interface{}) error {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
t := reflect.Indirect(reflect.ValueOf(bean)).Type() t := reflect.Indirect(reflect.ValueOf(bean)).Type()
defer session.Statement.Init() defer session.resetStatement()
if t.Kind() == reflect.String { if t.Kind() == reflect.String {
session.Statement.AltTableName = bean.(string) session.Statement.AltTableName = bean.(string)
} else if t.Kind() == reflect.Struct { } else if t.Kind() == reflect.Struct {
@ -599,7 +610,6 @@ func (statement *Statement) convertIdSql(sqlStr string) string {
if len(sqls) != 2 { if len(sqls) != 2 {
return "" return ""
} }
//fmt.Println("-----", col)
newsql := fmt.Sprintf("SELECT %v.%v FROM %v", statement.Engine.Quote(statement.TableName()), newsql := fmt.Sprintf("SELECT %v.%v FROM %v", statement.Engine.Quote(statement.TableName()),
statement.Engine.Quote(col.Name), sqls[1]) statement.Engine.Quote(col.Name), sqls[1])
return newsql return newsql
@ -728,7 +738,6 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
ids = make([]core.PK, 0) ids = make([]core.PK, 0)
if len(resultsSlice) > 0 { if len(resultsSlice) > 0 {
for _, data := range resultsSlice { for _, data := range resultsSlice {
//fmt.Println(data)
var id int64 var id int64
if v, ok := data[session.Statement.RefTable.PrimaryKeys[0]]; !ok { if v, ok := data[session.Statement.RefTable.PrimaryKeys[0]]; !ok {
return errors.New("no id") return errors.New("no id")
@ -930,7 +939,7 @@ func (session *Session) Get(bean interface{}) (bool, error) {
return false, err return false, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -939,7 +948,9 @@ func (session *Session) Get(bean interface{}) (bool, error) {
var sqlStr string var sqlStr string
var args []interface{} var args []interface{}
if session.Statement.RefTable == nil {
session.Statement.RefTable = session.Engine.autoMap(bean) session.Statement.RefTable = session.Engine.autoMap(bean)
}
if session.Statement.RawSQL == "" { if session.Statement.RawSQL == "" {
sqlStr, args = session.Statement.genGetSql(bean) sqlStr, args = session.Statement.genGetSql(bean)
@ -948,12 +959,14 @@ func (session *Session) Get(bean interface{}) (bool, error) {
args = session.Statement.RawParams args = session.Statement.RawParams
} }
if session.Statement.JoinStr == "" {
if cacher := session.Engine.getCacher2(session.Statement.RefTable); cacher != nil && session.Statement.UseCache { if cacher := session.Engine.getCacher2(session.Statement.RefTable); cacher != nil && session.Statement.UseCache {
has, err := session.cacheGet(bean, sqlStr, args...) has, err := session.cacheGet(bean, sqlStr, args...)
if err != ErrCacheFailed { if err != ErrCacheFailed {
return has, err return has, err
} }
} }
}
var rawRows *core.Rows var rawRows *core.Rows
session.queryPreprocess(&sqlStr, args...) session.queryPreprocess(&sqlStr, args...)
@ -991,7 +1004,7 @@ func (session *Session) Count(bean interface{}) (int64, error) {
return 0, err return 0, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1030,7 +1043,7 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1073,9 +1086,15 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
var args []interface{} var args []interface{}
if session.Statement.RawSQL == "" { if session.Statement.RawSQL == "" {
var columnStr string = session.Statement.ColumnStr var columnStr string = session.Statement.ColumnStr
if session.Statement.JoinStr == "" {
if columnStr == "" { if columnStr == "" {
columnStr = session.Statement.genColumnStr() columnStr = session.Statement.genColumnStr()
} }
} else {
if columnStr == "" {
columnStr = "*"
}
}
session.Statement.attachInSql() session.Statement.attachInSql()
@ -1086,6 +1105,7 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
args = session.Statement.RawParams args = session.Statement.RawParams
} }
if session.Statement.JoinStr == "" {
if cacher := session.Engine.getCacher2(table); cacher != nil && if cacher := session.Engine.getCacher2(table); cacher != nil &&
session.Statement.UseCache && session.Statement.UseCache &&
!session.Statement.IsDistinct { !session.Statement.IsDistinct {
@ -1096,20 +1116,13 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
err = nil // !nashtsai! reset err to nil for ErrCacheFailed err = nil // !nashtsai! reset err to nil for ErrCacheFailed
session.Engine.LogWarn("Cache Find Failed") session.Engine.LogWarn("Cache Find Failed")
} }
}
if sliceValue.Kind() != reflect.Map { if sliceValue.Kind() != reflect.Map {
var rawRows *core.Rows var rawRows *core.Rows
var stmt *core.Stmt var stmt *core.Stmt
session.queryPreprocess(&sqlStr, args...) session.queryPreprocess(&sqlStr, args...)
// err = session.queryRows(&stmt, &rawRows, sqlStr, args...)
// if err != nil {
// return err
// }
// if stmt != nil {
// defer stmt.Close()
// }
// defer rawRows.Close()
if session.IsAutoCommit { if session.IsAutoCommit {
stmt, err = session.doPrepare(sqlStr) stmt, err = session.doPrepare(sqlStr)
@ -1226,7 +1239,7 @@ func (session *Session) Ping() error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1239,7 +1252,7 @@ func (session *Session) isColumnExist(tableName string, col *core.Column) (bool,
if err != nil { if err != nil {
return false, err return false, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1254,7 +1267,7 @@ func (session *Session) isTableExist(tableName string) (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1268,7 +1281,7 @@ func (session *Session) isIndexExist(tableName, idxName string, unique bool) (bo
if err != nil { if err != nil {
return false, err return false, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1307,11 +1320,10 @@ func (session *Session) addColumn(colName string) error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
//fmt.Println(session.Statement.RefTable)
col := session.Statement.RefTable.GetColumn(colName) col := session.Statement.RefTable.GetColumn(colName)
sql, args := session.Statement.genAddColumnStr(col) sql, args := session.Statement.genAddColumnStr(col)
@ -1324,7 +1336,7 @@ func (session *Session) addIndex(tableName, idxName string) error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1340,11 +1352,10 @@ func (session *Session) addUnique(tableName, uqeName string) error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
//fmt.Println(uqeName, session.Statement.RefTable.Uniques)
index := session.Statement.RefTable.Indexes[uqeName] index := session.Statement.RefTable.Indexes[uqeName]
sqlStr := session.Engine.dialect.CreateIndexSql(tableName, index) sqlStr := session.Engine.dialect.CreateIndexSql(tableName, index)
_, err = session.exec(sqlStr) _, err = session.exec(sqlStr)
@ -1357,7 +1368,7 @@ func (session *Session) dropAll() error {
if err != nil { if err != nil {
return err return err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1402,9 +1413,9 @@ func row2map(rows *core.Rows, fields []string) (resultsMap map[string][]byte, er
return result, nil return result, nil
} }
func (session *Session) getField(dataStruct *reflect.Value, key string, table *core.Table) *reflect.Value { func (session *Session) getField(dataStruct *reflect.Value, key string, table *core.Table, idx int) *reflect.Value {
var col *core.Column var col *core.Column
if col = table.GetColumn(key); col == nil { if col = table.GetColumnIdx(key, idx); col == nil {
session.Engine.LogWarn(fmt.Sprintf("table %v's has not column %v. %v", table.Name, key, table.Columns())) session.Engine.LogWarn(fmt.Sprintf("table %v's has not column %v. %v", table.Name, key, table.Columns()))
return nil return nil
} }
@ -1448,13 +1459,22 @@ func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount i
} }
} }
var tempMap = make(map[string]int)
for ii, key := range fields { for ii, key := range fields {
if fieldValue := session.getField(&dataStruct, key, table); fieldValue != nil { var idx int
var ok bool
if idx, ok = tempMap[strings.ToLower(key)]; !ok {
idx = 0
} else {
idx = idx + 1
}
tempMap[strings.ToLower(key)] = idx
if fieldValue := session.getField(&dataStruct, key, table, idx); fieldValue != nil {
rawValue := reflect.Indirect(reflect.ValueOf(scanResults[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 {
//fmt.Println("ignore ...", key, rawValue)
continue continue
} }
@ -1485,9 +1505,6 @@ func (session *Session) row2Bean(rows *core.Rows, fields []string, fieldsCount i
vv := reflect.ValueOf(rawValue.Interface()) vv := reflect.ValueOf(rawValue.Interface())
fieldType := fieldValue.Type() fieldType := fieldValue.Type()
//fmt.Println("column name:", key, ", fieldType:", fieldType.String())
hasAssigned := false hasAssigned := false
switch fieldType.Kind() { switch fieldType.Kind() {
@ -1734,7 +1751,7 @@ func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{})
*sqlStr = filter.Do(*sqlStr, session.Engine.dialect, session.Statement.RefTable) *sqlStr = filter.Do(*sqlStr, session.Engine.dialect, session.Statement.RefTable)
} }
session.Engine.logSQL(*sqlStr, paramStr) session.Engine.logSQL(*sqlStr, paramStr...)
} }
func (session *Session) query(sqlStr string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) { func (session *Session) query(sqlStr string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
@ -1767,7 +1784,6 @@ func query(db *core.DB, sqlStr string, params ...interface{}) (resultsSlice []ma
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
//fmt.Println(rows)
return rows2maps(rows) return rows2maps(rows)
} }
@ -1777,7 +1793,7 @@ func (session *Session) Query(sqlStr string, paramStr ...interface{}) (resultsSl
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1793,7 +1809,7 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -1980,7 +1996,7 @@ func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -2034,11 +2050,9 @@ func (session *Session) byte2Time(col *core.Column, data []byte) (outTime time.T
} }
sdata = strings.TrimSpace(sdata) sdata = strings.TrimSpace(sdata)
//fmt.Println(sdata)
if session.Engine.dialect.DBType() == core.MYSQL && len(sdata) > 8 { if session.Engine.dialect.DBType() == core.MYSQL && len(sdata) > 8 {
sdata = sdata[len(sdata)-8:] sdata = sdata[len(sdata)-8:]
} }
//fmt.Println(sdata)
st := fmt.Sprintf("2006-01-02 %v", sdata) st := fmt.Sprintf("2006-01-02 %v", sdata)
x, err = time.ParseInLocation("2006-01-02 15:04:05", st, session.Engine.TZLocation) x, err = time.ParseInLocation("2006-01-02 15:04:05", st, session.Engine.TZLocation)
@ -2069,7 +2083,6 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value,
key := col.Name key := col.Name
fieldType := fieldValue.Type() fieldType := fieldValue.Type()
//fmt.Println("column name:", key, ", fieldType:", fieldType.String())
switch fieldType.Kind() { switch fieldType.Kind() {
case reflect.Complex64, reflect.Complex128: case reflect.Complex64, reflect.Complex128:
x := reflect.New(fieldType) x := reflect.New(fieldType)
@ -2578,7 +2591,6 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
} }
colPlaces := strings.Repeat("?, ", len(colNames)) colPlaces := strings.Repeat("?, ", len(colNames))
//fmt.Println(colNames, args)
colPlaces = colPlaces[0 : len(colPlaces)-2] colPlaces = colPlaces[0 : len(colPlaces)-2]
sqlStr := fmt.Sprintf("INSERT INTO %v%v%v (%v%v%v) VALUES (%v)", sqlStr := fmt.Sprintf("INSERT INTO %v%v%v (%v%v%v) VALUES (%v)",
@ -2748,7 +2760,7 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -2934,7 +2946,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -2988,7 +3000,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
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)+" = ?")
args = append(args, session.Engine.NowTime(table.Columns()[strings.ToLower(table.Updated)].SQLType.Name)) args = append(args, session.Engine.NowTime(table.UpdatedColumn().SQLType.Name))
} }
//for update action to like "column = column + ?" //for update action to like "column = column + ?"
@ -3009,7 +3021,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
var condition = "" var condition = ""
session.Statement.processIdParam() session.Statement.processIdParam()
st := session.Statement st := session.Statement
defer session.Statement.Init() defer session.resetStatement()
if st.WhereStr != "" { if st.WhereStr != "" {
condition = fmt.Sprintf("%v", st.WhereStr) condition = fmt.Sprintf("%v", st.WhereStr)
} }
@ -3187,7 +3199,7 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
if err != nil { if err != nil {
return 0, err return 0, err
} }
defer session.Statement.Init() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
defer session.Close() defer session.Close()
} }
@ -3332,6 +3344,7 @@ func genCols(table *core.Table, session *Session, bean interface{}, useCol bool,
args = append(args, session.Engine.NowTime(col.SQLType.Name)) 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 if !col.DefaultIsEmpty {
} else { } else {
arg, err := session.value2Interface(col, fieldValue) arg, err := session.value2Interface(col, fieldValue)
if err != nil { if err != nil {

View File

@ -1,6 +1,7 @@
package xorm package xorm
import ( import (
"errors"
"fmt" "fmt"
"strings" "strings"
@ -120,6 +121,11 @@ func (db *sqlite3) GetColumns(tableName string) ([]string, map[string]*core.Colu
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
break
}
if name == "" {
return nil, nil, errors.New("no table named " + tableName)
} }
nStart := strings.Index(name, "(") nStart := strings.Index(name, "(")

View File

@ -277,11 +277,11 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{},
if !includeAutoIncr && col.IsAutoIncrement { if !includeAutoIncr && col.IsAutoIncrement {
continue continue
} }
//
//fmt.Println(engine.dialect.DBType(), Text)
if engine.dialect.DBType() == core.MSSQL && col.SQLType.Name == core.Text { if engine.dialect.DBType() == core.MSSQL && col.SQLType.Name == core.Text {
continue continue
} }
fieldValuePtr, err := col.ValueOf(bean) fieldValuePtr, err := col.ValueOf(bean)
if err != nil { if err != nil {
engine.LogError(err) engine.LogError(err)
@ -292,6 +292,7 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{},
fieldType := reflect.TypeOf(fieldValue.Interface()) fieldType := reflect.TypeOf(fieldValue.Interface())
requiredField := useAllCols requiredField := useAllCols
includeNil := useAllCols
if b, ok := mustColumnMap[strings.ToLower(col.Name)]; ok { if b, ok := mustColumnMap[strings.ToLower(col.Name)]; ok {
if b { if b {
requiredField = true requiredField = true
@ -382,7 +383,6 @@ func buildUpdates(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)
} else { } else {
engine.autoMapType(fieldValue) engine.autoMapType(fieldValue)
if table, ok := engine.Tables[fieldValue.Type()]; ok { if table, ok := engine.Tables[fieldValue.Type()]; ok {
@ -470,8 +470,7 @@ func buildConditions(engine *Engine, table *core.Table, bean interface{},
if !includeAutoIncr && col.IsAutoIncrement { if !includeAutoIncr && col.IsAutoIncrement {
continue continue
} }
//
//fmt.Println(engine.dialect.DBType(), Text)
if engine.dialect.DBType() == core.MSSQL && col.SQLType.Name == core.Text { if engine.dialect.DBType() == core.MSSQL && col.SQLType.Name == core.Text {
continue continue
} }
@ -555,7 +554,6 @@ 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)
} else { } else {
engine.autoMapType(fieldValue) engine.autoMapType(fieldValue)
if table, ok := engine.Tables[fieldValue.Type()]; ok { if table, ok := engine.Tables[fieldValue.Type()]; ok {
@ -948,8 +946,13 @@ func (s *Statement) genDropSQL() string {
} }
func (statement *Statement) genGetSql(bean interface{}) (string, []interface{}) { func (statement *Statement) genGetSql(bean interface{}) (string, []interface{}) {
table := statement.Engine.autoMap(bean) var table *core.Table
if statement.RefTable == nil {
table = statement.Engine.autoMap(bean)
statement.RefTable = table statement.RefTable = table
} else {
table = statement.RefTable
}
colNames, args := buildConditions(statement.Engine, table, bean, true, true, colNames, args := buildConditions(statement.Engine, table, bean, true, true,
false, true, statement.allUseBool, statement.useAllCols, false, true, statement.allUseBool, statement.useAllCols,
@ -959,9 +962,15 @@ func (statement *Statement) genGetSql(bean interface{}) (string, []interface{})
statement.BeanArgs = args statement.BeanArgs = args
var columnStr string = statement.ColumnStr var columnStr string = statement.ColumnStr
if statement.JoinStr == "" {
if columnStr == "" { if columnStr == "" {
columnStr = statement.genColumnStr() columnStr = statement.genColumnStr()
} }
} else {
if columnStr == "" {
columnStr = "*"
}
}
statement.attachInSql() // !admpub! fix bug:Iterate func missing "... IN (...)" statement.attachInSql() // !admpub! fix bug:Iterate func missing "... IN (...)"
return statement.genSelectSql(columnStr), append(statement.Params, statement.BeanArgs...) return statement.genSelectSql(columnStr), append(statement.Params, statement.BeanArgs...)