golint and comments

This commit is contained in:
Lunny Xiao 2016-07-11 11:29:34 +08:00
parent b8b1711cde
commit ea9a4495ac
3 changed files with 190 additions and 141 deletions

148
engine.go
View File

@ -161,11 +161,16 @@ func (engine *Engine) quoteTable(keyName string) string {
return engine.dialect.QuoteStr() + keyName + engine.dialect.QuoteStr() return engine.dialect.QuoteStr() + keyName + engine.dialect.QuoteStr()
} }
// SqlType A simple wrapper to dialect's core.SqlType method // SqlType will be depracated, please use SQLType instead
func (engine *Engine) SqlType(c *core.Column) string { func (engine *Engine) SqlType(c *core.Column) string {
return engine.dialect.SqlType(c) return engine.dialect.SqlType(c)
} }
// SQLType A simple wrapper to dialect's core.SqlType method
func (engine *Engine) SQLType(c *core.Column) string {
return engine.dialect.SqlType(c)
}
// AutoIncrStr Database's autoincrement statement // AutoIncrStr Database's autoincrement statement
func (engine *Engine) AutoIncrStr() string { func (engine *Engine) AutoIncrStr() string {
return engine.dialect.AutoIncrStr() return engine.dialect.AutoIncrStr()
@ -265,9 +270,8 @@ func (engine *Engine) logSQLQueryTime(sqlStr string, args []interface{}, executi
engine.logger.Infof("[sql] %s - took: %v", sqlStr, execDuration) engine.logger.Infof("[sql] %s - took: %v", sqlStr, execDuration)
} }
return stmt, res, err return stmt, res, err
} else {
return executionBlock()
} }
return executionBlock()
} }
func (engine *Engine) logSQLExecutionTime(sqlStr string, args []interface{}, executionBlock func() (sql.Result, error)) (sql.Result, error) { func (engine *Engine) logSQLExecutionTime(sqlStr string, args []interface{}, executionBlock func() (sql.Result, error)) (sql.Result, error) {
@ -281,24 +285,29 @@ func (engine *Engine) logSQLExecutionTime(sqlStr string, args []interface{}, exe
engine.logger.Infof("[sql] %s - took: %v", sqlStr, execDuration) engine.logger.Infof("[sql] %s - took: %v", sqlStr, execDuration)
} }
return res, err return res, err
} else {
return executionBlock()
} }
return executionBlock()
} }
// Sql method let's you manualy write raw sql and operate // Sql will be depracated, please use SQL instead
// For example:
//
// engine.Sql("select * from user").Find(&users)
//
// This code will execute "select * from user" and set the records to users
//
func (engine *Engine) Sql(querystring string, args ...interface{}) *Session { func (engine *Engine) Sql(querystring string, args ...interface{}) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Sql(querystring, args...) return session.Sql(querystring, args...)
} }
// SQL method let's you manualy write raw SQL and operate
// For example:
//
// engine.SQL("select * from user").Find(&users)
//
// This code will execute "select * from user" and set the records to users
func (engine *Engine) SQL(querystring string, args ...interface{}) *Session {
session := engine.NewSession()
session.IsAutoClose = true
return session.SQL(querystring, args...)
}
// NoAutoTime Default if your struct has "created" or "updated" filed tag, the fields // NoAutoTime Default if your struct has "created" or "updated" filed tag, the fields
// will automatically be filled with current time when Insert or Update // will automatically be filled with current time when Insert or Update
// invoked. Call NoAutoTime if you dont' want to fill automatically. // invoked. Call NoAutoTime if you dont' want to fill automatically.
@ -618,7 +627,7 @@ func (engine *Engine) dumpTables(tables []*core.Table, w io.Writer, tp ...core.D
return nil return nil
} }
// use cascade or not // Cascade use cascade or not
func (engine *Engine) Cascade(trueOrFalse ...bool) *Session { func (engine *Engine) Cascade(trueOrFalse ...bool) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
@ -632,42 +641,49 @@ func (engine *Engine) Where(querystring string, args ...interface{}) *Session {
return session.Where(querystring, args...) return session.Where(querystring, args...)
} }
// Id mehtod provoide a condition as (id) = ? // Id will be depracated, please use ID instead
func (engine *Engine) Id(id interface{}) *Session { func (engine *Engine) Id(id interface{}) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Id(id) return session.Id(id)
} }
// Apply before Processor, affected bean is passed to closure arg // ID mehtod provoide a condition as (id) = ?
func (engine *Engine) ID(id interface{}) *Session {
session := engine.NewSession()
session.IsAutoClose = true
return session.ID(id)
}
// Before apply before Processor, affected bean is passed to closure arg
func (engine *Engine) Before(closures func(interface{})) *Session { func (engine *Engine) Before(closures func(interface{})) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Before(closures) return session.Before(closures)
} }
// Apply after insert Processor, affected bean is passed to closure arg // After apply after insert Processor, affected bean is passed to closure arg
func (engine *Engine) After(closures func(interface{})) *Session { func (engine *Engine) After(closures func(interface{})) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.After(closures) return session.After(closures)
} }
// set charset when create table, only support mysql now // Charset set charset when create table, only support mysql now
func (engine *Engine) Charset(charset string) *Session { func (engine *Engine) Charset(charset string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Charset(charset) return session.Charset(charset)
} }
// set store engine when create table, only support mysql now // StoreEngine set store engine when create table, only support mysql now
func (engine *Engine) StoreEngine(storeEngine string) *Session { func (engine *Engine) StoreEngine(storeEngine string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.StoreEngine(storeEngine) return session.StoreEngine(storeEngine)
} }
// use for distinct columns. Caution: when you are using cache, // Distinct use for distinct columns. Caution: when you are using cache,
// distinct will not be cached because cache system need id, // distinct will not be cached because cache system need id,
// but distinct will not provide id // but distinct will not provide id
func (engine *Engine) Distinct(columns ...string) *Session { func (engine *Engine) Distinct(columns ...string) *Session {
@ -676,32 +692,35 @@ func (engine *Engine) Distinct(columns ...string) *Session {
return session.Distinct(columns...) return session.Distinct(columns...)
} }
// Select customerize your select columns or contents
func (engine *Engine) Select(str string) *Session { func (engine *Engine) Select(str string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Select(str) return session.Select(str)
} }
// only use the paramters as select or update columns // Cols only use the paramters as select or update columns
func (engine *Engine) Cols(columns ...string) *Session { func (engine *Engine) Cols(columns ...string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Cols(columns...) return session.Cols(columns...)
} }
// AllCols indicates that all columns should be use
func (engine *Engine) AllCols() *Session { func (engine *Engine) AllCols() *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.AllCols() return session.AllCols()
} }
// MustCols specify some columns must use even if they are empty
func (engine *Engine) MustCols(columns ...string) *Session { func (engine *Engine) MustCols(columns ...string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.MustCols(columns...) return session.MustCols(columns...)
} }
// Xorm automatically retrieve condition according struct, but // UseBool xorm automatically retrieve condition according struct, but
// if struct has bool field, it will ignore them. So use UseBool // if struct has bool field, it will ignore them. So use UseBool
// to tell system to do not ignore them. // to tell system to do not ignore them.
// If no paramters, it will use all the bool field of struct, or // If no paramters, it will use all the bool field of struct, or
@ -712,78 +731,77 @@ func (engine *Engine) UseBool(columns ...string) *Session {
return session.UseBool(columns...) return session.UseBool(columns...)
} }
// Only not use the paramters as select or update columns // Omit only not use the paramters as select or update columns
func (engine *Engine) Omit(columns ...string) *Session { func (engine *Engine) Omit(columns ...string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Omit(columns...) return session.Omit(columns...)
} }
// Set null when column is zero-value and nullable for update // Nullable set null when column is zero-value and nullable for update
func (engine *Engine) Nullable(columns ...string) *Session { func (engine *Engine) Nullable(columns ...string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Nullable(columns...) return session.Nullable(columns...)
} }
// This method will generate "column IN (?, ?)" // In will generate "column IN (?, ?)"
func (engine *Engine) In(column string, args ...interface{}) *Session { func (engine *Engine) In(column string, args ...interface{}) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.In(column, args...) return session.In(column, args...)
} }
// Method Inc provides a update string like "column = column + ?" // Incr provides a update string like "column = column + ?"
func (engine *Engine) Incr(column string, arg ...interface{}) *Session { func (engine *Engine) Incr(column string, arg ...interface{}) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Incr(column, arg...) return session.Incr(column, arg...)
} }
// Method Decr provides a update string like "column = column - ?" // Decr provides a update string like "column = column - ?"
func (engine *Engine) Decr(column string, arg ...interface{}) *Session { func (engine *Engine) Decr(column string, arg ...interface{}) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Decr(column, arg...) return session.Decr(column, arg...)
} }
// Method SetExpr provides a update string like "column = {expression}" // SetExpr provides a update string like "column = {expression}"
func (engine *Engine) SetExpr(column string, expression string) *Session { func (engine *Engine) SetExpr(column string, expression string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.SetExpr(column, expression) return session.SetExpr(column, expression)
} }
// Temporarily change the Get, Find, Update's table // Table temporarily change the Get, Find, Update's table
func (engine *Engine) Table(tableNameOrBean interface{}) *Session { func (engine *Engine) Table(tableNameOrBean interface{}) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Table(tableNameOrBean) return session.Table(tableNameOrBean)
} }
// set the table alias // Alias set the table alias
func (engine *Engine) Alias(alias string) *Session { func (engine *Engine) Alias(alias string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Alias(alias) return session.Alias(alias)
} }
// This method will generate "LIMIT start, limit" // Limit will generate "LIMIT start, limit"
func (engine *Engine) Limit(limit int, start ...int) *Session { func (engine *Engine) Limit(limit int, start ...int) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Limit(limit, start...) return session.Limit(limit, start...)
} }
// Method Desc will generate "ORDER BY column1 DESC, column2 DESC" // Desc will generate "ORDER BY column1 DESC, column2 DESC"
// This will
func (engine *Engine) Desc(colNames ...string) *Session { func (engine *Engine) Desc(colNames ...string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Desc(colNames...) return session.Desc(colNames...)
} }
// Method Asc will generate "ORDER BY column1,column2 Asc" // 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)
@ -795,28 +813,28 @@ func (engine *Engine) Asc(colNames ...string) *Session {
return session.Asc(colNames...) return session.Asc(colNames...)
} }
// Method OrderBy will generate "ORDER BY order" // OrderBy will generate "ORDER BY order"
func (engine *Engine) OrderBy(order string) *Session { func (engine *Engine) OrderBy(order string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.OrderBy(order) return session.OrderBy(order)
} }
// The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN // Join the join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
func (engine *Engine) Join(join_operator string, tablename interface{}, condition string, args ...interface{}) *Session { func (engine *Engine) Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.Join(join_operator, tablename, condition, args...) return session.Join(joinOperator, tablename, condition, args...)
} }
// Generate Group By statement // GroupBy generate group by statement
func (engine *Engine) GroupBy(keys string) *Session { func (engine *Engine) GroupBy(keys string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.GroupBy(keys) return session.GroupBy(keys)
} }
// Generate Having statement // Having generate having statement
func (engine *Engine) Having(conditions string) *Session { func (engine *Engine) Having(conditions string) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
@ -842,17 +860,20 @@ func (engine *Engine) autoMapType(v reflect.Value) *core.Table {
return table return table
} }
// GobRegister register one struct to gob for cache use
func (engine *Engine) GobRegister(v interface{}) *Engine { func (engine *Engine) GobRegister(v interface{}) *Engine {
//fmt.Printf("Type: %[1]T => Data: %[1]#v\n", v) //fmt.Printf("Type: %[1]T => Data: %[1]#v\n", v)
gob.Register(v) gob.Register(v)
return engine return engine
} }
// Table table struct
type Table struct { type Table struct {
*core.Table *core.Table
Name string Name string
} }
// TableInfo get table info according to bean's content
func (engine *Engine) TableInfo(bean interface{}) *Table { func (engine *Engine) TableInfo(bean interface{}) *Table {
v := rValue(bean) v := rValue(bean)
return &Table{engine.autoMapType(v), engine.tbName(v)} return &Table{engine.autoMapType(v), engine.tbName(v)}
@ -879,6 +900,7 @@ func (engine *Engine) newTable() *core.Table {
return table return table
} }
// TableName table name interface to define customerize table name
type TableName interface { type TableName interface {
TableName() string TableName() string
} }
@ -1035,7 +1057,7 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
preKey = k preKey = k
continue continue
} }
col.SQLType = core.SQLType{fs[0], 0, 0} col.SQLType = core.SQLType{Name: fs[0]}
if fs[0] == core.Enum && fs[1][0] == '\'' { //enum if fs[0] == core.Enum && fs[1][0] == '\'' { //enum
options := strings.Split(fs[1][0:len(fs[1])-1], ",") options := strings.Split(fs[1][0:len(fs[1])-1], ",")
col.EnumOptions = make(map[string]int) col.EnumOptions = make(map[string]int)
@ -1072,7 +1094,7 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
} }
} else { } else {
if _, ok := core.SqlTypes[k]; ok { if _, ok := core.SqlTypes[k]; ok {
col.SQLType = core.SQLType{k, 0, 0} col.SQLType = core.SQLType{Name: k}
} else if key != col.Default { } else if key != col.Default {
col.Name = key col.Name = key
} }
@ -1109,11 +1131,11 @@ func (engine *Engine) mapType(v reflect.Value) *core.Table {
var sqlType core.SQLType var sqlType core.SQLType
if fieldValue.CanAddr() { if fieldValue.CanAddr() {
if _, ok := fieldValue.Addr().Interface().(core.Conversion); ok { if _, ok := fieldValue.Addr().Interface().(core.Conversion); ok {
sqlType = core.SQLType{core.Text, 0, 0} sqlType = core.SQLType{Name: core.Text}
} }
} }
if _, ok := fieldValue.Interface().(core.Conversion); ok { if _, ok := fieldValue.Interface().(core.Conversion); ok {
sqlType = core.SQLType{core.Text, 0, 0} sqlType = core.SQLType{Name: core.Text}
} else { } else {
sqlType = core.Type2SQLType(fieldType) sqlType = core.Type2SQLType(fieldType)
} }
@ -1169,24 +1191,26 @@ func (engine *Engine) mapping(beans ...interface{}) (e error) {
return return
} }
// If a table has any reocrd // IsTableEmpty if a table has any reocrd
func (engine *Engine) IsTableEmpty(bean interface{}) (bool, error) { func (engine *Engine) IsTableEmpty(bean interface{}) (bool, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.IsTableEmpty(bean) return session.IsTableEmpty(bean)
} }
// If a table is exist // IsTableExist if a table is exist
func (engine *Engine) IsTableExist(beanOrTableName interface{}) (bool, error) { func (engine *Engine) IsTableExist(beanOrTableName interface{}) (bool, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.IsTableExist(beanOrTableName) return session.IsTableExist(beanOrTableName)
} }
// IdOf get id from one struct
func (engine *Engine) IdOf(bean interface{}) core.PK { func (engine *Engine) IdOf(bean interface{}) core.PK {
return engine.IdOfV(reflect.ValueOf(bean)) return engine.IdOfV(reflect.ValueOf(bean))
} }
// IdOfV get id from one value of struct
func (engine *Engine) IdOfV(rv reflect.Value) core.PK { func (engine *Engine) IdOfV(rv reflect.Value) core.PK {
v := reflect.Indirect(rv) v := reflect.Indirect(rv)
table := engine.autoMapType(v) table := engine.autoMapType(v)
@ -1205,14 +1229,14 @@ func (engine *Engine) IdOfV(rv reflect.Value) core.PK {
return core.PK(pk) return core.PK(pk)
} }
// create indexes // CreateIndexes create indexes
func (engine *Engine) CreateIndexes(bean interface{}) error { func (engine *Engine) CreateIndexes(bean interface{}) error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.CreateIndexes(bean) return session.CreateIndexes(bean)
} }
// create uniques // CreateUniques create uniques
func (engine *Engine) CreateUniques(bean interface{}) error { func (engine *Engine) CreateUniques(bean interface{}) error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
@ -1230,7 +1254,7 @@ func (engine *Engine) getCacher(v reflect.Value) core.Cacher {
return engine.Cacher return engine.Cacher
} }
// If enabled cache, clear the cache bean // ClearCacheBean 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 {
v := rValue(bean) v := rValue(bean)
t := v.Type() t := v.Type()
@ -1250,7 +1274,7 @@ func (engine *Engine) ClearCacheBean(bean interface{}, id string) error {
return nil return nil
} }
// If enabled cache, clear some tables' cache // ClearCache 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 {
v := rValue(bean) v := rValue(bean)
@ -1369,6 +1393,7 @@ func (engine *Engine) Sync(beans ...interface{}) error {
return nil return nil
} }
// Sync2 synchronize structs to database tables
func (engine *Engine) Sync2(beans ...interface{}) error { func (engine *Engine) Sync2(beans ...interface{}) error {
s := engine.NewSession() s := engine.NewSession()
defer s.Close() defer s.Close()
@ -1424,6 +1449,7 @@ func (engine *Engine) CreateTables(beans ...interface{}) error {
return session.Commit() return session.Commit()
} }
// DropTables drop specify tables
func (engine *Engine) DropTables(beans ...interface{}) error { func (engine *Engine) DropTables(beans ...interface{}) error {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
@ -1456,7 +1482,7 @@ func (engine *Engine) Exec(sql string, args ...interface{}) (sql.Result, error)
return session.Exec(sql, args...) return session.Exec(sql, args...)
} }
// Exec a raw sql and return records as []map[string][]byte // Query a raw sql and return records as []map[string][]byte
func (engine *Engine) Query(sql string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) { func (engine *Engine) Query(sql string, paramStr ...interface{}) (resultsSlice []map[string][]byte, err error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
@ -1470,7 +1496,7 @@ func (engine *Engine) Insert(beans ...interface{}) (int64, error) {
return session.Insert(beans...) return session.Insert(beans...)
} }
// Insert only one record // InsertOne insert only one record
func (engine *Engine) InsertOne(bean interface{}) (int64, error) { func (engine *Engine) InsertOne(bean interface{}) (int64, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
@ -1521,7 +1547,7 @@ func (engine *Engine) Iterate(bean interface{}, fun IterFunc) error {
return session.Iterate(bean, fun) return session.Iterate(bean, fun)
} }
// Return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields // Rows return sql.Rows compatible Rows obj, as a forward Iterator object for iterating record by record, bean's non-empty fields
// are conditions. // are conditions.
func (engine *Engine) Rows(bean interface{}) (*Rows, error) { func (engine *Engine) Rows(bean interface{}) (*Rows, error) {
session := engine.NewSession() session := engine.NewSession()
@ -1556,7 +1582,7 @@ func (engine *Engine) SumsInt(bean interface{}, colNames ...string) ([]int64, er
return session.SumsInt(bean, colNames...) return session.SumsInt(bean, colNames...)
} }
// Import SQL DDL file // ImportFile SQL DDL file
func (engine *Engine) ImportFile(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 {
@ -1566,7 +1592,7 @@ func (engine *Engine) ImportFile(ddlPath string) ([]sql.Result, error) {
return engine.Import(file) return engine.Import(file)
} }
// Import SQL DDL file // Import SQL DDL from io.Reader
func (engine *Engine) Import(r io.Reader) ([]sql.Result, error) { func (engine *Engine) Import(r io.Reader) ([]sql.Result, error) {
var results []sql.Result var results []sql.Result
var lastError error var lastError error
@ -1597,7 +1623,7 @@ func (engine *Engine) Import(r io.Reader) ([]sql.Result, error) {
results = append(results, result) results = append(results, result)
if err != nil { if err != nil {
return nil, err return nil, err
lastError = err //lastError = err
} }
} }
} }
@ -1605,27 +1631,27 @@ func (engine *Engine) Import(r io.Reader) ([]sql.Result, error) {
return results, lastError return results, lastError
} }
var ( // TZTime change one time to xorm time location
NULL_TIME time.Time
)
func (engine *Engine) TZTime(t time.Time) time.Time { func (engine *Engine) TZTime(t time.Time) time.Time {
if NULL_TIME != t { // if time is not initialized it's not suitable for Time.In() if !t.IsZero() { // if time is not initialized it's not suitable for Time.In()
return t.In(engine.TZLocation) return t.In(engine.TZLocation)
} }
return t return t
} }
// NowTime return current time
func (engine *Engine) NowTime(sqlTypeName string) interface{} { func (engine *Engine) NowTime(sqlTypeName string) interface{} {
t := time.Now() t := time.Now()
return engine.FormatTime(sqlTypeName, t) return engine.FormatTime(sqlTypeName, t)
} }
// NowTime2 return current time
func (engine *Engine) NowTime2(sqlTypeName string) (interface{}, time.Time) { func (engine *Engine) NowTime2(sqlTypeName string) (interface{}, time.Time) {
t := time.Now() t := time.Now()
return engine.FormatTime(sqlTypeName, t), t return engine.FormatTime(sqlTypeName, t), t
} }
// FormatTime format time
func (engine *Engine) FormatTime(sqlTypeName string, t time.Time) (v interface{}) { func (engine *Engine) FormatTime(sqlTypeName string, t time.Time) (v interface{}) {
return engine.formatTime(engine.TZLocation, sqlTypeName, t) return engine.formatTime(engine.TZLocation, sqlTypeName, t)
} }
@ -1676,7 +1702,7 @@ func (engine *Engine) formatTime(tz *time.Location, sqlTypeName string, t time.T
return return
} }
// Always disable struct tag "deleted" // Unscoped always disable struct tag "deleted"
func (engine *Engine) Unscoped() *Session { func (engine *Engine) Unscoped() *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true

38
rows.go
View File

@ -12,6 +12,7 @@ import (
"github.com/go-xorm/core" "github.com/go-xorm/core"
) )
// Rows rows wrapper a rows to
type Rows struct { type Rows struct {
NoTypeCheck bool NoTypeCheck bool
@ -52,24 +53,33 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
rows.session.saveLastSQL(sqlStr, args) rows.session.saveLastSQL(sqlStr, args)
var err error var err error
rows.stmt, err = rows.session.DB().Prepare(sqlStr) if rows.session.prepareStmt {
if err != nil { rows.stmt, err = rows.session.DB().Prepare(sqlStr)
rows.lastError = err if err != nil {
defer rows.Close() rows.lastError = err
return nil, err rows.Close()
} return nil, err
}
rows.rows, err = rows.stmt.Query(args...) rows.rows, err = rows.stmt.Query(args...)
if err != nil { if err != nil {
rows.lastError = err rows.lastError = err
defer rows.Close() rows.Close()
return nil, err return nil, err
}
} else {
rows.rows, err = rows.session.DB().Query(sqlStr, args...)
if err != nil {
rows.lastError = err
rows.Close()
return nil, err
}
} }
rows.fields, err = rows.rows.Columns() rows.fields, err = rows.rows.Columns()
if err != nil { if err != nil {
rows.lastError = err rows.lastError = err
defer rows.Close() rows.Close()
return nil, err return nil, err
} }
rows.fieldsCount = len(rows.fields) rows.fieldsCount = len(rows.fields)
@ -77,7 +87,7 @@ func newRows(session *Session, bean interface{}) (*Rows, error) {
return rows, nil return rows, nil
} }
// move cursor to next record, return false if end has reached // Next move cursor to next record, return false if end has reached
func (rows *Rows) Next() bool { func (rows *Rows) Next() bool {
if rows.lastError == nil && rows.rows != nil { if rows.lastError == nil && rows.rows != nil {
hasNext := rows.rows.Next() hasNext := rows.rows.Next()
@ -107,7 +117,7 @@ func (rows *Rows) Scan(bean interface{}) error {
return rows.session.row2Bean(rows.rows, rows.fields, rows.fieldsCount, bean) return rows.session.row2Bean(rows.rows, rows.fields, rows.fieldsCount, bean)
} }
// close session if session.IsAutoClose is true, and claimed any opened resources // Close session if session.IsAutoClose is true, and claimed any opened resources
func (rows *Rows) Close() error { func (rows *Rows) Close() error {
if rows.session.IsAutoClose { if rows.session.IsAutoClose {
defer rows.session.Close() defer rows.session.Close()

View File

@ -19,7 +19,7 @@ import (
"github.com/go-xorm/core" "github.com/go-xorm/core"
) )
// Struct Session keep a pointer to sql.DB and provides all execution of all // Session keep a pointer to sql.DB and provides all execution of all
// kind of database operations. // kind of database operations.
type Session struct { type Session struct {
db *core.DB db *core.DB
@ -106,19 +106,25 @@ func (session *Session) resetStatement() {
} }
} }
// Prepare // Prepare set a flag to session that should be prepare statment before execute query
func (session *Session) Prepare() *Session { func (session *Session) Prepare() *Session {
session.prepareStmt = true session.prepareStmt = true
return session return session
} }
// Sql provides raw sql input parameter. When you have a complex SQL statement // Sql will be deprecated, please use SQL instead.
// 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 {
session.Statement.Sql(querystring, args...) session.Statement.Sql(querystring, args...)
return session return session
} }
// 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.
func (session *Session) SQL(querystring string, args ...interface{}) *Session {
session.Statement.Sql(querystring, args...)
return session
}
// Where provides custom query condition. // Where provides custom query condition.
func (session *Session) Where(querystring string, args ...interface{}) *Session { func (session *Session) Where(querystring string, args ...interface{}) *Session {
session.Statement.Where(querystring, args...) session.Statement.Where(querystring, args...)
@ -137,12 +143,18 @@ func (session *Session) Or(querystring string, args ...interface{}) *Session {
return session return session
} }
// Id provides converting id as a query condition // Id will be deprecated, please use ID instead
func (session *Session) Id(id interface{}) *Session { func (session *Session) Id(id interface{}) *Session {
session.Statement.Id(id) session.Statement.Id(id)
return session return session
} }
// ID provides converting id as a query condition
func (session *Session) ID(id interface{}) *Session {
session.Statement.Id(id)
return session
}
// Before Apply before Processor, affected bean is passed to closure arg // Before Apply before Processor, affected bean is passed to closure arg
func (session *Session) Before(closures func(interface{})) *Session { func (session *Session) Before(closures func(interface{})) *Session {
if closures != nil { if closures != nil {
@ -213,13 +225,13 @@ func (session *Session) AllCols() *Session {
return session return session
} }
// MustCols // MustCols specify some columns must use even if they are empty
func (session *Session) MustCols(columns ...string) *Session { func (session *Session) MustCols(columns ...string) *Session {
session.Statement.MustCols(columns...) session.Statement.MustCols(columns...)
return session return session
} }
// NoCascade // NoCascade indicate that no cascade load child object
func (session *Session) NoCascade() *Session { func (session *Session) NoCascade() *Session {
session.Statement.UseCascade = false session.Statement.UseCascade = false
return session return session
@ -274,44 +286,44 @@ func (session *Session) NoAutoCondition(no ...bool) *Session {
return session return session
} }
// Method Limit provide limit and offset query condition // Limit provide limit and offset query condition
func (session *Session) Limit(limit int, start ...int) *Session { func (session *Session) Limit(limit int, start ...int) *Session {
session.Statement.Limit(limit, start...) session.Statement.Limit(limit, start...)
return session return session
} }
// Method OrderBy provide order by query condition, the input parameter is the content // OrderBy provide order by query condition, the input parameter is the content
// after order by on a sql statement. // after order by on a sql statement.
func (session *Session) OrderBy(order string) *Session { func (session *Session) OrderBy(order string) *Session {
session.Statement.OrderBy(order) session.Statement.OrderBy(order)
return session return session
} }
// Method Desc provide desc order by query condition, the input parameters are columns. // Desc provide desc order by query condition, the input parameters are columns.
func (session *Session) Desc(colNames ...string) *Session { func (session *Session) Desc(colNames ...string) *Session {
session.Statement.Desc(colNames...) session.Statement.Desc(colNames...)
return session return session
} }
// Method Asc provide asc order by query condition, the input parameters are columns. // Asc provide asc order by query condition, the input parameters are columns.
func (session *Session) Asc(colNames ...string) *Session { func (session *Session) Asc(colNames ...string) *Session {
session.Statement.Asc(colNames...) session.Statement.Asc(colNames...)
return session return session
} }
// Method StoreEngine is only avialble mysql dialect currently // StoreEngine is only avialble mysql dialect currently
func (session *Session) StoreEngine(storeEngine string) *Session { func (session *Session) StoreEngine(storeEngine string) *Session {
session.Statement.StoreEngine = storeEngine session.Statement.StoreEngine = storeEngine
return session return session
} }
// Method Charset is only avialble mysql dialect currently // Charset is only avialble mysql dialect currently
func (session *Session) Charset(charset string) *Session { func (session *Session) Charset(charset string) *Session {
session.Statement.Charset = charset session.Statement.Charset = charset
return session return session
} }
// Method Cascade indicates if loading sub Struct // Cascade indicates if loading sub Struct
func (session *Session) Cascade(trueOrFalse ...bool) *Session { func (session *Session) Cascade(trueOrFalse ...bool) *Session {
if len(trueOrFalse) >= 1 { if len(trueOrFalse) >= 1 {
session.Statement.UseCascade = trueOrFalse[0] session.Statement.UseCascade = trueOrFalse[0]
@ -611,7 +623,7 @@ func (session *Session) createAll() error {
return nil return nil
} }
// drop indexes // DropIndexes drop indexes
func (session *Session) DropIndexes(bean interface{}) error { func (session *Session) DropIndexes(bean interface{}) error {
v := rValue(bean) v := rValue(bean)
session.Statement.setRefValue(v) session.Statement.setRefValue(v)
@ -631,7 +643,7 @@ func (session *Session) DropIndexes(bean interface{}) error {
return nil return nil
} }
// drop table will drop table if exist, if drop failed, it will return error // DropTable drop table will drop table if exist, if drop failed, it will return error
func (session *Session) DropTable(beanOrTableName interface{}) error { func (session *Session) DropTable(beanOrTableName interface{}) error {
tableName, err := session.Engine.tableName(beanOrTableName) tableName, err := session.Engine.tableName(beanOrTableName)
if err != nil { if err != nil {
@ -838,8 +850,8 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in
sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr)) sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr))
ididxes := make(map[string]int) ididxes := make(map[string]int)
var ides []core.PK = make([]core.PK, 0) var ides []core.PK
var temps []interface{} = make([]interface{}, len(ids)) var temps = make([]interface{}, len(ids))
for idx, id := range ids { for idx, id := range ids {
sid, err := id.ToString() sid, err := id.ToString()
@ -1162,6 +1174,7 @@ func (session *Session) Sums(bean interface{}, columnNames ...string) ([]float64
return res, nil return res, nil
} }
// SumsInt sum specify columns and return as []int64 instead of []float64
func (session *Session) SumsInt(bean interface{}, columnNames ...string) ([]int64, error) { func (session *Session) SumsInt(bean interface{}, columnNames ...string) ([]int64, error) {
defer session.resetStatement() defer session.resetStatement()
if session.IsAutoClose { if session.IsAutoClose {
@ -1507,9 +1520,8 @@ func (session *Session) isIndexExist2(tableName string, cols []string, unique bo
if sliceEq(index.Cols, cols) { if sliceEq(index.Cols, cols) {
if unique { if unique {
return index.Type == core.UniqueType, nil return index.Type == core.UniqueType, nil
} else {
return index.Type == core.IndexType, nil
} }
return index.Type == core.IndexType, nil
} }
} }
return false, nil return false, nil
@ -1590,6 +1602,7 @@ func (session *Session) getField(dataStruct *reflect.Value, key string, table *c
return fieldValue return fieldValue
} }
// Cell cell is a result of one column field
type Cell *interface{} type Cell *interface{}
func (session *Session) rows2Beans(rows *core.Rows, fields []string, fieldsCount int, func (session *Session) rows2Beans(rows *core.Rows, fields []string, fieldsCount int,
@ -1940,7 +1953,7 @@ func (session *Session) _row2Bean(rows *core.Rows, fields []string, fieldsCount
//fieldValue.Set(reflect.ValueOf(v)) //fieldValue.Set(reflect.ValueOf(v))
fieldValue.Set(structInter.Elem()) fieldValue.Set(structInter.Elem())
} else { } else {
return errors.New("cascade obj is not exist!") return errors.New("cascade obj is not exist")
} }
} }
} else { } else {
@ -3579,7 +3592,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
} }
} }
var sqlStr, inSql string var sqlStr, inSQL string
var inArgs []interface{} var inArgs []interface{}
doIncVer := false doIncVer := false
var verValue *reflect.Value var verValue *reflect.Value
@ -3590,12 +3603,12 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
} else { } else {
condition = fmt.Sprintf("WHERE %v = ?", session.Engine.Quote(table.Version)) condition = fmt.Sprintf("WHERE %v = ?", session.Engine.Quote(table.Version))
} }
inSql, inArgs = session.Statement.genInSql() inSQL, inArgs = session.Statement.genInSql()
if len(inSql) > 0 { if len(inSQL) > 0 {
if condition != "" { if condition != "" {
condition += " " + session.Engine.Dialect().AndStr() + " " + inSql condition += " " + session.Engine.Dialect().AndStr() + " " + inSQL
} else { } else {
condition = "WHERE " + inSql condition = "WHERE " + inSQL
} }
} }
@ -3620,12 +3633,12 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
if condition != "" { if condition != "" {
condition = "WHERE " + condition condition = "WHERE " + condition
} }
inSql, inArgs = session.Statement.genInSql() inSQL, inArgs = session.Statement.genInSql()
if len(inSql) > 0 { if len(inSQL) > 0 {
if condition != "" { if condition != "" {
condition += " " + session.Engine.Dialect().AndStr() + " " + inSql condition += " " + session.Engine.Dialect().AndStr() + " " + inSQL
} else { } else {
condition = "WHERE " + inSql condition = "WHERE " + inSQL
} }
} }
@ -3795,62 +3808,62 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
} else { } else {
condition = strings.Join(colNames, " "+andStr+" ") condition = strings.Join(colNames, " "+andStr+" ")
} }
inSql, inArgs := session.Statement.genInSql() inSQL, inArgs := session.Statement.genInSql()
if len(inSql) > 0 { if len(inSQL) > 0 {
if len(condition) > 0 { if len(condition) > 0 {
condition += " " + andStr + " " condition += " " + andStr + " "
} }
condition += inSql condition += inSQL
args = append(args, inArgs...) args = append(args, inArgs...)
} }
if len(condition) == 0 && session.Statement.LimitN == 0 { if len(condition) == 0 && session.Statement.LimitN == 0 {
return 0, ErrNeedDeletedCond return 0, ErrNeedDeletedCond
} }
var deleteSql, realSql string var deleteSQL, realSQL string
var tableName = session.Engine.Quote(session.Statement.TableName()) var tableName = session.Engine.Quote(session.Statement.TableName())
if len(condition) > 0 { if len(condition) > 0 {
deleteSql = fmt.Sprintf("DELETE FROM %v WHERE %v", tableName, condition) deleteSQL = fmt.Sprintf("DELETE FROM %v WHERE %v", tableName, condition)
} else { } else {
deleteSql = fmt.Sprintf("DELETE FROM %v", tableName) deleteSQL = fmt.Sprintf("DELETE FROM %v", tableName)
} }
var orderSql string var orderSQL string
if len(session.Statement.OrderStr) > 0 { if len(session.Statement.OrderStr) > 0 {
orderSql += fmt.Sprintf(" ORDER BY %s", session.Statement.OrderStr) orderSQL += fmt.Sprintf(" ORDER BY %s", session.Statement.OrderStr)
} }
if session.Statement.LimitN > 0 { if session.Statement.LimitN > 0 {
orderSql += fmt.Sprintf(" LIMIT %d", session.Statement.LimitN) orderSQL += fmt.Sprintf(" LIMIT %d", session.Statement.LimitN)
} }
if len(orderSql) > 0 { if len(orderSQL) > 0 {
switch session.Engine.dialect.DBType() { switch session.Engine.dialect.DBType() {
case core.POSTGRES: case core.POSTGRES:
inSql := fmt.Sprintf("ctid IN (SELECT ctid FROM %s%s)", tableName, orderSql) inSQL := fmt.Sprintf("ctid IN (SELECT ctid FROM %s%s)", tableName, orderSQL)
if len(condition) > 0 { if len(condition) > 0 {
deleteSql += " AND " + inSql deleteSQL += " AND " + inSQL
} else { } else {
deleteSql += " WHERE " + inSql deleteSQL += " WHERE " + inSQL
} }
case core.SQLITE: case core.SQLITE:
inSql := fmt.Sprintf("rowid IN (SELECT rowid FROM %s%s)", tableName, orderSql) inSQL := fmt.Sprintf("rowid IN (SELECT rowid FROM %s%s)", tableName, orderSQL)
if len(condition) > 0 { if len(condition) > 0 {
deleteSql += " AND " + inSql deleteSQL += " AND " + inSQL
} else { } else {
deleteSql += " WHERE " + inSql deleteSQL += " WHERE " + inSQL
} }
// TODO: how to handle delete limit on mssql? // TODO: how to handle delete limit on mssql?
case core.MSSQL: case core.MSSQL:
return 0, ErrNotImplemented return 0, ErrNotImplemented
default: default:
deleteSql += orderSql deleteSQL += orderSQL
} }
} }
argsForCache := make([]interface{}, 0, len(args)*2) argsForCache := make([]interface{}, 0, len(args)*2)
if session.Statement.unscoped || table.DeletedColumn() == nil { // tag "deleted" is disabled if session.Statement.unscoped || table.DeletedColumn() == nil { // tag "deleted" is disabled
realSql = deleteSql realSQL = deleteSQL
copy(argsForCache, args) copy(argsForCache, args)
argsForCache = append(session.Statement.Params, argsForCache...) argsForCache = append(session.Statement.Params, argsForCache...)
} else { } else {
@ -3859,32 +3872,32 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
argsForCache = append(session.Statement.Params, argsForCache...) argsForCache = append(session.Statement.Params, argsForCache...)
deletedColumn := table.DeletedColumn() deletedColumn := table.DeletedColumn()
realSql = fmt.Sprintf("UPDATE %v SET %v = ? WHERE %v", realSQL = fmt.Sprintf("UPDATE %v SET %v = ? WHERE %v",
session.Engine.Quote(session.Statement.TableName()), session.Engine.Quote(session.Statement.TableName()),
session.Engine.Quote(deletedColumn.Name), session.Engine.Quote(deletedColumn.Name),
condition) condition)
if len(orderSql) > 0 { if len(orderSQL) > 0 {
switch session.Engine.dialect.DBType() { switch session.Engine.dialect.DBType() {
case core.POSTGRES: case core.POSTGRES:
inSql := fmt.Sprintf("ctid IN (SELECT ctid FROM %s%s)", tableName, orderSql) inSQL := fmt.Sprintf("ctid IN (SELECT ctid FROM %s%s)", tableName, orderSQL)
if len(condition) > 0 { if len(condition) > 0 {
realSql += " AND " + inSql realSQL += " AND " + inSQL
} else { } else {
realSql += " WHERE " + inSql realSQL += " WHERE " + inSQL
} }
case core.SQLITE: case core.SQLITE:
inSql := fmt.Sprintf("rowid IN (SELECT rowid FROM %s%s)", tableName, orderSql) inSQL := fmt.Sprintf("rowid IN (SELECT rowid FROM %s%s)", tableName, orderSQL)
if len(condition) > 0 { if len(condition) > 0 {
realSql += " AND " + inSql realSQL += " AND " + inSQL
} else { } else {
realSql += " WHERE " + inSql realSQL += " WHERE " + inSQL
} }
// TODO: how to handle delete limit on mssql? // TODO: how to handle delete limit on mssql?
case core.MSSQL: case core.MSSQL:
return 0, ErrNotImplemented return 0, ErrNotImplemented
default: default:
realSql += orderSql realSQL += orderSQL
} }
} }
@ -3906,10 +3919,10 @@ func (session *Session) Delete(bean interface{}) (int64, error) {
args = append(session.Statement.Params, args...) args = append(session.Statement.Params, args...)
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 {
session.cacheDelete(deleteSql, argsForCache...) session.cacheDelete(deleteSQL, argsForCache...)
} }
res, err := session.exec(realSql, args...) res, err := session.exec(realSQL, args...)
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -3966,8 +3979,8 @@ func (session *Session) tbNameNoSchema(table *core.Table) string {
} }
// Sync2 synchronize structs to database tables // Sync2 synchronize structs to database tables
func (s *Session) Sync2(beans ...interface{}) error { func (session *Session) Sync2(beans ...interface{}) error {
engine := s.Engine engine := session.Engine
tables, err := engine.DBMetas() tables, err := engine.DBMetas()
if err != nil { if err != nil {
@ -3980,7 +3993,7 @@ func (s *Session) Sync2(beans ...interface{}) error {
v := rValue(bean) v := rValue(bean)
table := engine.mapType(v) table := engine.mapType(v)
structTables = append(structTables, table) structTables = append(structTables, table)
var tbName = s.tbNameNoSchema(table) var tbName = session.tbNameNoSchema(table)
var oriTable *core.Table var oriTable *core.Table
for _, tb := range tables { for _, tb := range tables {
@ -3991,17 +4004,17 @@ func (s *Session) Sync2(beans ...interface{}) error {
} }
if oriTable == nil { if oriTable == nil {
err = s.StoreEngine(s.Statement.StoreEngine).CreateTable(bean) err = session.StoreEngine(session.Statement.StoreEngine).CreateTable(bean)
if err != nil { if err != nil {
return err return err
} }
err = s.CreateUniques(bean) err = session.CreateUniques(bean)
if err != nil { if err != nil {
return err return err
} }
err = s.CreateIndexes(bean) err = session.CreateIndexes(bean)
if err != nil { if err != nil {
return err return err
} }
@ -4137,7 +4150,7 @@ func (s *Session) Sync2(beans ...interface{}) error {
for _, table := range tables { for _, table := range tables {
var oriTable *core.Table var oriTable *core.Table
for _, structTable := range structTables { for _, structTable := range structTables {
if equalNoCase(table.Name, s.tbNameNoSchema(structTable)) { if equalNoCase(table.Name, session.tbNameNoSchema(structTable)) {
oriTable = structTable oriTable = structTable
break break
} }