join parameters support & many comments

This commit is contained in:
Lunny Xiao 2016-03-29 09:17:06 +08:00
parent a2a2456fa2
commit 7d2967c786
6 changed files with 106 additions and 55 deletions

View File

@ -1 +1 @@
xorm v0.5.2.0324 xorm v0.5.2.0329

View File

@ -54,6 +54,7 @@ type Engine struct {
disableGlobalCache bool disableGlobalCache bool
} }
// ShowSQL show SQL statment or not on logger if log level is great than INFO
func (engine *Engine) ShowSQL(show ...bool) { func (engine *Engine) ShowSQL(show ...bool) {
engine.logger.ShowSQL(show...) engine.logger.ShowSQL(show...)
if len(show) == 0 { if len(show) == 0 {
@ -63,6 +64,7 @@ func (engine *Engine) ShowSQL(show ...bool) {
} }
} }
// ShowExecTime show SQL statment and execute time or not on logger if log level is great than INFO
func (engine *Engine) ShowExecTime(show ...bool) { func (engine *Engine) ShowExecTime(show ...bool) {
if len(show) == 0 { if len(show) == 0 {
engine.showExecTime = true engine.showExecTime = true
@ -71,43 +73,51 @@ func (engine *Engine) ShowExecTime(show ...bool) {
} }
} }
// Logger return the logger interface
func (engine *Engine) Logger() core.ILogger { func (engine *Engine) Logger() core.ILogger {
return engine.logger return engine.logger
} }
// SetLogger set the new logger
func (engine *Engine) SetLogger(logger core.ILogger) { func (engine *Engine) SetLogger(logger core.ILogger) {
engine.logger = logger engine.logger = logger
engine.dialect.SetLogger(logger) engine.dialect.SetLogger(logger)
} }
// SetDisableGlobalCache disable global cache or not
func (engine *Engine) SetDisableGlobalCache(disable bool) { func (engine *Engine) SetDisableGlobalCache(disable bool) {
if engine.disableGlobalCache != disable { if engine.disableGlobalCache != disable {
engine.disableGlobalCache = disable engine.disableGlobalCache = disable
} }
} }
// DriverName return the current sql driver's name
func (engine *Engine) DriverName() string { func (engine *Engine) DriverName() string {
return engine.dialect.DriverName() return engine.dialect.DriverName()
} }
// DataSourceName return the current connection string
func (engine *Engine) DataSourceName() string { func (engine *Engine) DataSourceName() string {
return engine.dialect.DataSourceName() return engine.dialect.DataSourceName()
} }
// SetMapper set the name mapping rules
func (engine *Engine) SetMapper(mapper core.IMapper) { func (engine *Engine) SetMapper(mapper core.IMapper) {
engine.SetTableMapper(mapper) engine.SetTableMapper(mapper)
engine.SetColumnMapper(mapper) engine.SetColumnMapper(mapper)
} }
// SetTableMapper set the table name mapping rule
func (engine *Engine) SetTableMapper(mapper core.IMapper) { func (engine *Engine) SetTableMapper(mapper core.IMapper) {
engine.TableMapper = mapper engine.TableMapper = mapper
} }
// SetColumnMapper set the column name mapping rule
func (engine *Engine) SetColumnMapper(mapper core.IMapper) { func (engine *Engine) SetColumnMapper(mapper core.IMapper) {
engine.ColumnMapper = mapper engine.ColumnMapper = mapper
} }
// If engine's database support batch insert records like // SupportInsertMany If engine's database support batch insert records like
// "insert into user values (name, age), (name, age)". // "insert into user values (name, age), (name, age)".
// When the return is ture, then engine.Insert(&users) will // When the return is ture, then engine.Insert(&users) will
// generate batch sql and exeute. // generate batch sql and exeute.
@ -115,13 +125,13 @@ func (engine *Engine) SupportInsertMany() bool {
return engine.dialect.SupportInsertMany() return engine.dialect.SupportInsertMany()
} }
// Engine's database use which charactor as quote. // QuoteStr Engine's database use which charactor as quote.
// mysql, sqlite use ` and postgres use " // mysql, sqlite use ` and postgres use "
func (engine *Engine) QuoteStr() string { func (engine *Engine) QuoteStr() string {
return engine.dialect.QuoteStr() return engine.dialect.QuoteStr()
} }
// Use QuoteStr quote the string sql // Quote Use QuoteStr quote the string sql
func (engine *Engine) Quote(sql string) string { func (engine *Engine) Quote(sql string) string {
return engine.quoteTable(sql) return engine.quoteTable(sql)
} }
@ -160,12 +170,12 @@ func (engine *Engine) quoteTable(keyName string) string {
return engine.dialect.QuoteStr() + keyName + engine.dialect.QuoteStr() return engine.dialect.QuoteStr() + keyName + engine.dialect.QuoteStr()
} }
// A simple wrapper to dialect's core.SqlType method // SqlType A simple wrapper to dialect's core.SqlType method
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)
} }
// 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()
} }
@ -175,22 +185,17 @@ func (engine *Engine) SetMaxOpenConns(conns int) {
engine.db.SetMaxOpenConns(conns) engine.db.SetMaxOpenConns(conns)
} }
// @Deprecated // SetMaxIdleConns set the max idle connections on pool, default is 2
func (engine *Engine) SetMaxConns(conns int) {
engine.SetMaxOpenConns(conns)
}
// SetMaxIdleConns
func (engine *Engine) SetMaxIdleConns(conns int) { func (engine *Engine) SetMaxIdleConns(conns int) {
engine.db.SetMaxIdleConns(conns) engine.db.SetMaxIdleConns(conns)
} }
// SetDefaltCacher set the default cacher. Xorm's default not enable cacher. // SetDefaultCacher set the default cacher. Xorm's default not enable cacher.
func (engine *Engine) SetDefaultCacher(cacher core.Cacher) { func (engine *Engine) SetDefaultCacher(cacher core.Cacher) {
engine.Cacher = cacher engine.Cacher = cacher
} }
// If you has set default cacher, and you want temporilly stop use cache, // NoCache If you has set default cacher, and you want temporilly stop use cache,
// you can use NoCache() // you can use NoCache()
func (engine *Engine) NoCache() *Session { func (engine *Engine) NoCache() *Session {
session := engine.NewSession() session := engine.NewSession()
@ -198,13 +203,14 @@ func (engine *Engine) NoCache() *Session {
return session.NoCache() return session.NoCache()
} }
// NoCascade If you do not want to auto cascade load object
func (engine *Engine) NoCascade() *Session { func (engine *Engine) NoCascade() *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.NoCascade() return session.NoCascade()
} }
// Set a table use a special cacher // MapCacher 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)
tb := engine.autoMapType(v) tb := engine.autoMapType(v)
@ -216,15 +222,17 @@ func (engine *Engine) NewDB() (*core.DB, error) {
return core.OpenDialect(engine.dialect) return core.OpenDialect(engine.dialect)
} }
// DB return the wrapper of sql.DB
func (engine *Engine) DB() *core.DB { func (engine *Engine) DB() *core.DB {
return engine.db return engine.db
} }
// Dialect return database dialect
func (engine *Engine) Dialect() core.Dialect { func (engine *Engine) Dialect() core.Dialect {
return engine.dialect return engine.dialect
} }
// New a session // NewSession New a session
func (engine *Engine) NewSession() *Session { func (engine *Engine) NewSession() *Session {
session := &Session{Engine: engine} session := &Session{Engine: engine}
session.Init() session.Init()
@ -287,37 +295,42 @@ func (engine *Engine) logSQLExecutionTime(sqlStr string, args []interface{}, exe
} }
} }
// LogError logging error
func (engine *Engine) LogError(contents ...interface{}) { func (engine *Engine) LogError(contents ...interface{}) {
engine.logger.Err(contents...) engine.logger.Err(contents...)
} }
// LogErrorf logging errorf
func (engine *Engine) LogErrorf(format string, contents ...interface{}) { func (engine *Engine) LogErrorf(format string, contents ...interface{}) {
engine.logger.Errf(format, contents...) engine.logger.Errf(format, contents...)
} }
// logging info // LogInfo logging info
func (engine *Engine) LogInfo(contents ...interface{}) { func (engine *Engine) LogInfo(contents ...interface{}) {
engine.logger.Info(contents...) engine.logger.Info(contents...)
} }
// LogInfof logging infof
func (engine *Engine) LogInfof(format string, contents ...interface{}) { func (engine *Engine) LogInfof(format string, contents ...interface{}) {
engine.logger.Infof(format, contents...) engine.logger.Infof(format, contents...)
} }
// logging debug // LogDebug logging debug
func (engine *Engine) LogDebug(contents ...interface{}) { func (engine *Engine) LogDebug(contents ...interface{}) {
engine.logger.Debug(contents...) engine.logger.Debug(contents...)
} }
// LogDebugf logging debugf
func (engine *Engine) LogDebugf(format string, contents ...interface{}) { func (engine *Engine) LogDebugf(format string, contents ...interface{}) {
engine.logger.Debugf(format, contents...) engine.logger.Debugf(format, contents...)
} }
// logging warn // LogWarn logging warn
func (engine *Engine) LogWarn(contents ...interface{}) { func (engine *Engine) LogWarn(contents ...interface{}) {
engine.logger.Warning(contents...) engine.logger.Warning(contents...)
} }
// LogWarnf logging warnf
func (engine *Engine) LogWarnf(format string, contents ...interface{}) { func (engine *Engine) LogWarnf(format string, contents ...interface{}) {
engine.logger.Warningf(format, contents...) engine.logger.Warningf(format, contents...)
} }
@ -335,7 +348,7 @@ func (engine *Engine) Sql(querystring string, args ...interface{}) *Session {
return session.Sql(querystring, args...) return session.Sql(querystring, args...)
} }
// 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.
func (engine *Engine) NoAutoTime() *Session { func (engine *Engine) NoAutoTime() *Session {
@ -344,13 +357,14 @@ func (engine *Engine) NoAutoTime() *Session {
return session.NoAutoTime() return session.NoAutoTime()
} }
// NoAutoCondition disable auto generate Where condition from bean or not
func (engine *Engine) NoAutoCondition(no ...bool) *Session { func (engine *Engine) NoAutoCondition(no ...bool) *Session {
session := engine.NewSession() session := engine.NewSession()
session.IsAutoClose = true session.IsAutoClose = true
return session.NoAutoCondition(no...) return session.NoAutoCondition(no...)
} }
// Retrieve all tables, columns, indexes' informations from database. // DBMetas Retrieve all tables, columns, indexes' informations from database.
func (engine *Engine) DBMetas() ([]*core.Table, error) { func (engine *Engine) DBMetas() ([]*core.Table, error) {
tables, err := engine.dialect.GetTables() tables, err := engine.dialect.GetTables()
if err != nil { if err != nil {
@ -818,10 +832,10 @@ func (engine *Engine) OrderBy(order string) *Session {
} }
// The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to 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) *Session { func (engine *Engine) Join(join_operator 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) return session.Join(join_operator, tablename, condition, args...)
} }
// Generate Group By statement // Generate Group By statement

View File

@ -18,6 +18,7 @@ const (
DEFAULT_LOG_LEVEL = core.LOG_DEBUG DEFAULT_LOG_LEVEL = core.LOG_DEBUG
) )
// SimpleLogger is the default implment of core.ILogger
type SimpleLogger struct { type SimpleLogger struct {
DEBUG *log.Logger DEBUG *log.Logger
ERR *log.Logger ERR *log.Logger
@ -29,14 +30,17 @@ type SimpleLogger struct {
var _ core.ILogger = &SimpleLogger{} var _ core.ILogger = &SimpleLogger{}
// NewSimpleLogger use a special io.Writer as logger output
func NewSimpleLogger(out io.Writer) *SimpleLogger { func NewSimpleLogger(out io.Writer) *SimpleLogger {
return NewSimpleLogger2(out, DEFAULT_LOG_PREFIX, DEFAULT_LOG_FLAG) return NewSimpleLogger2(out, DEFAULT_LOG_PREFIX, DEFAULT_LOG_FLAG)
} }
// NewSimpleLogger2 let you customrize your logger prefix and flag
func NewSimpleLogger2(out io.Writer, prefix string, flag int) *SimpleLogger { func NewSimpleLogger2(out io.Writer, prefix string, flag int) *SimpleLogger {
return NewSimpleLogger3(out, prefix, flag, DEFAULT_LOG_LEVEL) return NewSimpleLogger3(out, prefix, flag, DEFAULT_LOG_LEVEL)
} }
// NewSimpleLogger3 let you customrize your logger prefix and flag and logLevel
func NewSimpleLogger3(out io.Writer, prefix string, flag int, l core.LogLevel) *SimpleLogger { func NewSimpleLogger3(out io.Writer, prefix string, flag int, l core.LogLevel) *SimpleLogger {
return &SimpleLogger{ return &SimpleLogger{
DEBUG: log.New(out, fmt.Sprintf("%s [debug] ", prefix), flag), DEBUG: log.New(out, fmt.Sprintf("%s [debug] ", prefix), flag),
@ -47,6 +51,7 @@ func NewSimpleLogger3(out io.Writer, prefix string, flag int, l core.LogLevel) *
} }
} }
// Err implement core.ILogger
func (s *SimpleLogger) Err(v ...interface{}) (err error) { func (s *SimpleLogger) Err(v ...interface{}) (err error) {
if s.level <= core.LOG_ERR { if s.level <= core.LOG_ERR {
s.ERR.Println(v...) s.ERR.Println(v...)
@ -54,6 +59,7 @@ func (s *SimpleLogger) Err(v ...interface{}) (err error) {
return return
} }
// Errf implement core.ILogger
func (s *SimpleLogger) Errf(format string, v ...interface{}) (err error) { func (s *SimpleLogger) Errf(format string, v ...interface{}) (err error) {
if s.level <= core.LOG_ERR { if s.level <= core.LOG_ERR {
s.ERR.Printf(format, v...) s.ERR.Printf(format, v...)
@ -61,6 +67,7 @@ func (s *SimpleLogger) Errf(format string, v ...interface{}) (err error) {
return return
} }
// Debug implement core.ILogger
func (s *SimpleLogger) Debug(v ...interface{}) (err error) { func (s *SimpleLogger) Debug(v ...interface{}) (err error) {
if s.level <= core.LOG_DEBUG { if s.level <= core.LOG_DEBUG {
s.DEBUG.Println(v...) s.DEBUG.Println(v...)
@ -68,6 +75,7 @@ func (s *SimpleLogger) Debug(v ...interface{}) (err error) {
return return
} }
// Debugf implement core.ILogger
func (s *SimpleLogger) Debugf(format string, v ...interface{}) (err error) { func (s *SimpleLogger) Debugf(format string, v ...interface{}) (err error) {
if s.level <= core.LOG_DEBUG { if s.level <= core.LOG_DEBUG {
s.DEBUG.Printf(format, v...) s.DEBUG.Printf(format, v...)
@ -75,6 +83,7 @@ func (s *SimpleLogger) Debugf(format string, v ...interface{}) (err error) {
return return
} }
// Info implement core.ILogger
func (s *SimpleLogger) Info(v ...interface{}) (err error) { func (s *SimpleLogger) Info(v ...interface{}) (err error) {
if s.level <= core.LOG_INFO { if s.level <= core.LOG_INFO {
s.INFO.Println(v...) s.INFO.Println(v...)
@ -82,6 +91,7 @@ func (s *SimpleLogger) Info(v ...interface{}) (err error) {
return return
} }
// Infof implement core.ILogger
func (s *SimpleLogger) Infof(format string, v ...interface{}) (err error) { func (s *SimpleLogger) Infof(format string, v ...interface{}) (err error) {
if s.level <= core.LOG_INFO { if s.level <= core.LOG_INFO {
s.INFO.Printf(format, v...) s.INFO.Printf(format, v...)
@ -89,6 +99,7 @@ func (s *SimpleLogger) Infof(format string, v ...interface{}) (err error) {
return return
} }
// Warning implement core.ILogger
func (s *SimpleLogger) Warning(v ...interface{}) (err error) { func (s *SimpleLogger) Warning(v ...interface{}) (err error) {
if s.level <= core.LOG_WARNING { if s.level <= core.LOG_WARNING {
s.WARN.Println(v...) s.WARN.Println(v...)
@ -96,6 +107,7 @@ func (s *SimpleLogger) Warning(v ...interface{}) (err error) {
return return
} }
// Warningf implement core.ILogger
func (s *SimpleLogger) Warningf(format string, v ...interface{}) (err error) { func (s *SimpleLogger) Warningf(format string, v ...interface{}) (err error) {
if s.level <= core.LOG_WARNING { if s.level <= core.LOG_WARNING {
s.WARN.Printf(format, v...) s.WARN.Printf(format, v...)
@ -103,15 +115,18 @@ func (s *SimpleLogger) Warningf(format string, v ...interface{}) (err error) {
return return
} }
// Level implement core.ILogger
func (s *SimpleLogger) Level() core.LogLevel { func (s *SimpleLogger) Level() core.LogLevel {
return s.level return s.level
} }
// SetLevel implement core.ILogger
func (s *SimpleLogger) SetLevel(l core.LogLevel) (err error) { func (s *SimpleLogger) SetLevel(l core.LogLevel) (err error) {
s.level = l s.level = l
return return
} }
// ShowSQL implement core.ILogger
func (s *SimpleLogger) ShowSQL(show ...bool) { func (s *SimpleLogger) ShowSQL(show ...bool) {
if len(show) == 0 { if len(show) == 0 {
s.showSQL = true s.showSQL = true
@ -120,6 +135,7 @@ func (s *SimpleLogger) ShowSQL(show ...bool) {
s.showSQL = show[0] s.showSQL = show[0]
} }
// IsShowSQL implement core.ILogger
func (s *SimpleLogger) IsShowSQL() bool { func (s *SimpleLogger) IsShowSQL() bool {
return s.showSQL return s.showSQL
} }

View File

@ -309,31 +309,32 @@ func (session *Session) Cascade(trueOrFalse ...bool) *Session {
return session return session
} }
// Method NoCache ask this session do not retrieve data from cache system and // NoCache ask this session do not retrieve data from cache system and
// get data from database directly. // get data from database directly.
func (session *Session) NoCache() *Session { func (session *Session) NoCache() *Session {
session.Statement.UseCache = false session.Statement.UseCache = false
return session return session
} }
//The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN // Join join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
func (session *Session) Join(join_operator string, tablename interface{}, condition string) *Session { func (session *Session) Join(joinOperator string, tablename interface{}, condition string, args ...interface{}) *Session {
session.Statement.Join(join_operator, tablename, condition) session.Statement.Join(joinOperator, tablename, condition, args...)
return session return session
} }
// Generate Group By statement // GroupBy Generate Group By statement
func (session *Session) GroupBy(keys string) *Session { func (session *Session) GroupBy(keys string) *Session {
session.Statement.GroupBy(keys) session.Statement.GroupBy(keys)
return session return session
} }
// Generate Having statement // Having Generate Having statement
func (session *Session) Having(conditions string) *Session { func (session *Session) Having(conditions string) *Session {
session.Statement.Having(conditions) session.Statement.Having(conditions)
return session return session
} }
// DB db return the wrapper of sql.DB
func (session *Session) DB() *core.DB { func (session *Session) DB() *core.DB {
if session.db == nil { if session.db == nil {
session.db = session.Engine.db session.db = session.Engine.db
@ -357,7 +358,7 @@ func (session *Session) Begin() error {
return nil return nil
} }
// When using transaction, you can rollback if any error // Rollback When using transaction, you can rollback if any error
func (session *Session) Rollback() error { func (session *Session) Rollback() error {
if !session.IsAutoCommit && !session.IsCommitedOrRollbacked { if !session.IsAutoCommit && !session.IsCommitedOrRollbacked {
session.saveLastSQL(session.Engine.dialect.RollBackStr()) session.saveLastSQL(session.Engine.dialect.RollBackStr())
@ -367,7 +368,7 @@ func (session *Session) Rollback() error {
return nil return nil
} }
// When using transaction, Commit will commit all operations. // Commit When using transaction, Commit will commit all operations.
func (session *Session) Commit() error { func (session *Session) Commit() error {
if !session.IsAutoCommit && !session.IsCommitedOrRollbacked { if !session.IsAutoCommit && !session.IsCommitedOrRollbacked {
session.saveLastSQL("COMMIT") session.saveLastSQL("COMMIT")
@ -521,7 +522,7 @@ func (session *Session) Exec(sqlStr string, args ...interface{}) (sql.Result, er
return session.exec(sqlStr, args...) return session.exec(sqlStr, args...)
} }
// this function create a table according a bean // CreateTable create a table according a bean
func (session *Session) CreateTable(bean interface{}) error { func (session *Session) CreateTable(bean interface{}) error {
v := rValue(bean) v := rValue(bean)
session.Statement.RefTable = session.Engine.mapType(v) session.Statement.RefTable = session.Engine.mapType(v)
@ -534,7 +535,7 @@ func (session *Session) CreateTable(bean interface{}) error {
return session.createOneTable() return session.createOneTable()
} }
// create indexes // CreateIndexes create indexes
func (session *Session) CreateIndexes(bean interface{}) error { func (session *Session) CreateIndexes(bean interface{}) error {
v := rValue(bean) v := rValue(bean)
session.Statement.RefTable = session.Engine.mapType(v) session.Statement.RefTable = session.Engine.mapType(v)
@ -554,7 +555,7 @@ func (session *Session) CreateIndexes(bean interface{}) error {
return nil return nil
} }
// create uniques // CreateUniques create uniques
func (session *Session) CreateUniques(bean interface{}) error { func (session *Session) CreateUniques(bean interface{}) error {
v := rValue(bean) v := rValue(bean)
session.Statement.RefTable = session.Engine.mapType(v) session.Statement.RefTable = session.Engine.mapType(v)
@ -1242,7 +1243,7 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
var sqlStr string var sqlStr string
var args []interface{} var args []interface{}
if session.Statement.RawSQL == "" { if session.Statement.RawSQL == "" {
var columnStr string = session.Statement.ColumnStr var columnStr = session.Statement.ColumnStr
if len(session.Statement.selectStr) > 0 { if len(session.Statement.selectStr) > 0 {
columnStr = session.Statement.selectStr columnStr = session.Statement.selectStr
} else { } else {
@ -1265,11 +1266,11 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{})
} }
} }
session.Statement.Params = append(session.Statement.Params, session.Statement.BeanArgs...) session.Statement.Params = append(session.Statement.joinArgs, append(session.Statement.Params, session.Statement.BeanArgs...)...)
session.Statement.attachInSql() session.Statement.attachInSql()
sqlStr = session.Statement.genSelectSql(columnStr) sqlStr = session.Statement.genSelectSQL(columnStr)
args = session.Statement.Params args = session.Statement.Params
// for mssql and use limit // for mssql and use limit
qs := strings.Count(sqlStr, "?") qs := strings.Count(sqlStr, "?")

View File

@ -37,7 +37,7 @@ type exprParam struct {
expr string expr string
} }
// statement save all the sql info for executing SQL // Statement save all the sql info for executing SQL
type Statement struct { type Statement struct {
RefTable *core.Table RefTable *core.Table
Engine *Engine Engine *Engine
@ -48,6 +48,7 @@ type Statement struct {
Params []interface{} Params []interface{}
OrderStr string OrderStr string
JoinStr string JoinStr string
joinArgs []interface{}
GroupByStr string GroupByStr string
HavingStr string HavingStr string
ColumnStr string ColumnStr string
@ -91,6 +92,7 @@ func (statement *Statement) Init() {
statement.OrderStr = "" statement.OrderStr = ""
statement.UseCascade = true statement.UseCascade = true
statement.JoinStr = "" statement.JoinStr = ""
statement.joinArgs = make([]interface{}, 0)
statement.GroupByStr = "" statement.GroupByStr = ""
statement.HavingStr = "" statement.HavingStr = ""
statement.ColumnStr = "" statement.ColumnStr = ""
@ -428,12 +430,27 @@ func buildUpdates(engine *Engine, table *core.Table, bean interface{},
return colNames, args return colNames, args
} }
func (statement *Statement) needTableName() bool {
return len(statement.JoinStr) > 0
}
func (statement *Statement) colName(col *core.Column, tableName string) string {
if statement.needTableName() {
var nm = tableName
if len(statement.TableAlias) > 0 {
nm = statement.TableAlias
}
return statement.Engine.Quote(nm) + "." + statement.Engine.Quote(col.Name)
}
return statement.Engine.Quote(col.Name)
}
// Auto generating conditions according a struct // Auto generating conditions according a struct
func buildConditions(engine *Engine, table *core.Table, bean interface{}, func buildConditions(engine *Engine, table *core.Table, bean interface{},
includeVersion bool, includeUpdated bool, includeNil bool, includeVersion bool, includeUpdated bool, includeNil bool,
includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool, includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool,
mustColumnMap map[string]bool, tableName, aliasName string, addedTableName bool) ([]string, []interface{}) { mustColumnMap map[string]bool, tableName, aliasName string, addedTableName bool) ([]string, []interface{}) {
colNames := make([]string, 0) var colNames []string
var args = make([]interface{}, 0) var args = make([]interface{}, 0)
for _, col := range table.Columns() { for _, col := range table.Columns() {
if !includeVersion && col.IsVersion { if !includeVersion && col.IsVersion {
@ -960,7 +977,7 @@ func (statement *Statement) Asc(colNames ...string) *Statement {
} }
//The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN //The join_operator should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
func (statement *Statement) Join(join_operator string, tablename interface{}, condition string) *Statement { func (statement *Statement) Join(join_operator string, tablename interface{}, condition string, args ...interface{}) *Statement {
var buf bytes.Buffer var buf bytes.Buffer
if len(statement.JoinStr) > 0 { if len(statement.JoinStr) > 0 {
fmt.Fprintf(&buf, "%v %v JOIN ", statement.JoinStr, join_operator) fmt.Fprintf(&buf, "%v %v JOIN ", statement.JoinStr, join_operator)
@ -1003,6 +1020,7 @@ func (statement *Statement) Join(join_operator string, tablename interface{}, co
fmt.Fprintf(&buf, " ON %v", condition) fmt.Fprintf(&buf, " ON %v", condition)
statement.JoinStr = buf.String() statement.JoinStr = buf.String()
statement.joinArgs = args
return statement return statement
} }
@ -1140,9 +1158,10 @@ func (statement *Statement) genGetSql(bean interface{}) (string, []interface{})
if len(statement.selectStr) > 0 { if len(statement.selectStr) > 0 {
columnStr = statement.selectStr columnStr = statement.selectStr
} else { } else {
// TODO: always generate column names, not use * even if join
if len(statement.JoinStr) == 0 { if len(statement.JoinStr) == 0 {
if len(columnStr) == 0 { if len(columnStr) == 0 {
if statement.GroupByStr != "" { if len(statement.GroupByStr) > 0 {
columnStr = statement.Engine.Quote(strings.Replace(statement.GroupByStr, ",", statement.Engine.Quote(","), -1)) columnStr = statement.Engine.Quote(strings.Replace(statement.GroupByStr, ",", statement.Engine.Quote(","), -1))
} else { } else {
columnStr = statement.genColumnStr() columnStr = statement.genColumnStr()
@ -1150,7 +1169,7 @@ func (statement *Statement) genGetSql(bean interface{}) (string, []interface{})
} }
} else { } else {
if len(columnStr) == 0 { if len(columnStr) == 0 {
if statement.GroupByStr != "" { if len(statement.GroupByStr) > 0 {
columnStr = statement.Engine.Quote(strings.Replace(statement.GroupByStr, ",", statement.Engine.Quote(","), -1)) columnStr = statement.Engine.Quote(strings.Replace(statement.GroupByStr, ",", statement.Engine.Quote(","), -1))
} else { } else {
columnStr = "*" columnStr = "*"
@ -1160,7 +1179,7 @@ func (statement *Statement) genGetSql(bean interface{}) (string, []interface{})
} }
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(append(statement.joinArgs, statement.Params...), statement.BeanArgs...)
} }
func (s *Statement) genAddColumnStr(col *core.Column) (string, []interface{}) { func (s *Statement) genAddColumnStr(col *core.Column) (string, []interface{}) {
@ -1203,15 +1222,15 @@ func (statement *Statement) genCountSql(bean interface{}) (string, []interface{}
} }
// count(index fieldname) > count(0) > count(*) // count(index fieldname) > count(0) > count(*)
var id string = "*" var id = "*"
if statement.Engine.Dialect().DBType() == "ql" { if statement.Engine.Dialect().DBType() == "ql" {
id = "" id = ""
} }
statement.attachInSql() statement.attachInSql()
return statement.genSelectSql(fmt.Sprintf("count(%v)", id)), append(statement.Params, statement.BeanArgs...) return statement.genSelectSQL(fmt.Sprintf("count(%v)", id)), append(append(statement.joinArgs, statement.Params...), statement.BeanArgs...)
} }
func (statement *Statement) genSelectSql(columnStr string) (a string) { func (statement *Statement) genSelectSQL(columnStr string) (a string) {
var distinct string var distinct string
if statement.IsDistinct { if statement.IsDistinct {
distinct = "DISTINCT " distinct = "DISTINCT "
@ -1322,11 +1341,12 @@ func (statement *Statement) processIdParam() {
if statement.IdParam != nil { if statement.IdParam != nil {
if statement.Engine.dialect.DBType() != "ql" { if statement.Engine.dialect.DBType() != "ql" {
for i, col := range statement.RefTable.PKColumns() { for i, col := range statement.RefTable.PKColumns() {
var colName = statement.colName(col, statement.TableName())
if i < len(*(statement.IdParam)) { if i < len(*(statement.IdParam)) {
statement.And(fmt.Sprintf("%v %s ?", statement.Engine.Quote(col.Name), statement.And(fmt.Sprintf("%v %s ?", colName,
statement.Engine.dialect.EqStr()), (*(statement.IdParam))[i]) statement.Engine.dialect.EqStr()), (*(statement.IdParam))[i])
} else { } else {
statement.And(fmt.Sprintf("%v %s ?", statement.Engine.Quote(col.Name), statement.And(fmt.Sprintf("%v %s ?", colName,
statement.Engine.dialect.EqStr()), "") statement.Engine.dialect.EqStr()), "")
} }
} }

12
xorm.go
View File

@ -5,7 +5,6 @@
package xorm package xorm
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"reflect" "reflect"
@ -17,7 +16,8 @@ import (
) )
const ( const (
Version string = "0.5.2.0324" // Version show the xorm's version
Version string = "0.5.2.0329"
) )
func regDrvsNDialects() bool { func regDrvsNDialects() bool {
@ -49,13 +49,13 @@ func close(engine *Engine) {
engine.Close() engine.Close()
} }
// new a db manager according to the parameter. Currently support four // NewEngine new a db manager according to the parameter. Currently support four
// drivers // drivers
func NewEngine(driverName string, dataSourceName string) (*Engine, error) { func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
regDrvsNDialects() regDrvsNDialects()
driver := core.QueryDriver(driverName) driver := core.QueryDriver(driverName)
if driver == nil { if driver == nil {
return nil, errors.New(fmt.Sprintf("Unsupported driver name: %v", driverName)) return nil, fmt.Errorf("Unsupported driver name: %v", driverName)
} }
uri, err := driver.Parse(driverName, dataSourceName) uri, err := driver.Parse(driverName, dataSourceName)
@ -65,7 +65,7 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
dialect := core.QueryDialect(uri.DbType) dialect := core.QueryDialect(uri.DbType)
if dialect == nil { if dialect == nil {
return nil, errors.New(fmt.Sprintf("Unsupported dialect type: %v", uri.DbType)) return nil, fmt.Errorf("Unsupported dialect type: %v", uri.DbType)
} }
db, err := core.Open(driverName, dataSourceName) db, err := core.Open(driverName, dataSourceName)
@ -97,7 +97,7 @@ func NewEngine(driverName string, dataSourceName string) (*Engine, error) {
return engine, nil return engine, nil
} }
// clone an engine // Clone clone an engine
func (engine *Engine) Clone() (*Engine, error) { func (engine *Engine) Clone() (*Engine, error) {
return NewEngine(engine.DriverName(), engine.DataSourceName()) return NewEngine(engine.DriverName(), engine.DataSourceName())
} }