summaryrefslogtreecommitdiffstats
path: root/vendor/xorm.io/xorm/session.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/xorm.io/xorm/session.go')
-rw-r--r--vendor/xorm.io/xorm/session.go192
1 files changed, 84 insertions, 108 deletions
diff --git a/vendor/xorm.io/xorm/session.go b/vendor/xorm.io/xorm/session.go
index 6b8bfbaf59..761b14152f 100644
--- a/vendor/xorm.io/xorm/session.go
+++ b/vendor/xorm.io/xorm/session.go
@@ -6,10 +6,14 @@ package xorm
import (
"context"
+ "crypto/rand"
+ "crypto/sha256"
"database/sql"
+ "encoding/hex"
"errors"
"fmt"
"hash/crc32"
+ "io"
"reflect"
"strings"
"time"
@@ -19,6 +23,7 @@ import (
"xorm.io/xorm/core"
"xorm.io/xorm/internal/json"
"xorm.io/xorm/internal/statements"
+ "xorm.io/xorm/log"
"xorm.io/xorm/schemas"
)
@@ -42,24 +47,24 @@ func (e ErrFieldIsNotValid) Error() string {
return fmt.Sprintf("field %s is not valid on table %s", e.FieldName, e.TableName)
}
-type sessionType int
+type sessionType bool
const (
- engineSession sessionType = iota
- groupSession
+ engineSession sessionType = false
+ groupSession sessionType = true
)
// Session keep a pointer to sql.DB and provides all execution of all
// kind of database operations.
type Session struct {
- db *core.DB
engine *Engine
tx *core.Tx
statement *statements.Statement
isAutoCommit bool
isCommitedOrRollbacked bool
isAutoClose bool
-
+ isClosed bool
+ prepareStmt bool
// Automatically reset the statement after operations that execute a SQL
// query such as Count(), Find(), Get(), ...
autoResetStatement bool
@@ -70,81 +75,101 @@ type Session struct {
afterDeleteBeans map[interface{}]*[]func(interface{})
// --
- beforeClosures []func(interface{})
- afterClosures []func(interface{})
-
+ beforeClosures []func(interface{})
+ afterClosures []func(interface{})
afterProcessors []executedProcessor
- prepareStmt bool
- stmtCache map[uint32]*core.Stmt //key: hash.Hash32 of (queryStr, len(queryStr))
+ stmtCache map[uint32]*core.Stmt //key: hash.Hash32 of (queryStr, len(queryStr))
lastSQL string
lastSQLArgs []interface{}
- showSQL bool
ctx context.Context
sessionType sessionType
}
-// Clone copy all the session's content and return a new session
-func (session *Session) Clone() *Session {
- var sess = *session
- return &sess
+func newSessionID() string {
+ hash := sha256.New()
+ _, err := io.CopyN(hash, rand.Reader, 50)
+ if err != nil {
+ return "????????????????????"
+ }
+ md := hash.Sum(nil)
+ mdStr := hex.EncodeToString(md)
+ return mdStr[0:20]
}
-// Init reset the session as the init status.
-func (session *Session) Init() {
- session.statement = statements.NewStatement(
- session.engine.dialect,
- session.engine.tagParser,
- session.engine.DatabaseTZ,
- )
- session.db = session.engine.db
- session.isAutoCommit = true
- session.isCommitedOrRollbacked = false
- session.isAutoClose = false
- session.autoResetStatement = true
- session.prepareStmt = false
-
- // !nashtsai! is lazy init better?
- session.afterInsertBeans = make(map[interface{}]*[]func(interface{}), 0)
- session.afterUpdateBeans = make(map[interface{}]*[]func(interface{}), 0)
- session.afterDeleteBeans = make(map[interface{}]*[]func(interface{}), 0)
- session.beforeClosures = make([]func(interface{}), 0)
- session.afterClosures = make([]func(interface{}), 0)
- session.stmtCache = make(map[uint32]*core.Stmt)
-
- session.afterProcessors = make([]executedProcessor, 0)
-
- session.lastSQL = ""
- session.lastSQLArgs = []interface{}{}
+func newSession(engine *Engine) *Session {
+ var ctx context.Context
+ if engine.logSessionID {
+ ctx = context.WithValue(engine.defaultContext, log.SessionIDKey, newSessionID())
+ } else {
+ ctx = engine.defaultContext
+ }
- session.ctx = session.engine.defaultContext
+ return &Session{
+ ctx: ctx,
+ engine: engine,
+ tx: nil,
+ statement: statements.NewStatement(
+ engine.dialect,
+ engine.tagParser,
+ engine.DatabaseTZ,
+ ),
+ isClosed: false,
+ isAutoCommit: true,
+ isCommitedOrRollbacked: false,
+ isAutoClose: false,
+ autoResetStatement: true,
+ prepareStmt: false,
+
+ afterInsertBeans: make(map[interface{}]*[]func(interface{}), 0),
+ afterUpdateBeans: make(map[interface{}]*[]func(interface{}), 0),
+ afterDeleteBeans: make(map[interface{}]*[]func(interface{}), 0),
+ beforeClosures: make([]func(interface{}), 0),
+ afterClosures: make([]func(interface{}), 0),
+ afterProcessors: make([]executedProcessor, 0),
+ stmtCache: make(map[uint32]*core.Stmt),
+
+ lastSQL: "",
+ lastSQLArgs: make([]interface{}, 0),
+
+ sessionType: engineSession,
+ }
}
// Close release the connection from pool
-func (session *Session) Close() {
+func (session *Session) Close() error {
for _, v := range session.stmtCache {
- v.Close()
+ if err := v.Close(); err != nil {
+ return err
+ }
}
- if session.db != nil {
+ if !session.isClosed {
// When Close be called, if session is a transaction and do not call
// Commit or Rollback, then call Rollback.
if session.tx != nil && !session.isCommitedOrRollbacked {
- session.Rollback()
+ if err := session.Rollback(); err != nil {
+ return err
+ }
}
session.tx = nil
session.stmtCache = nil
- session.db = nil
+ session.isClosed = true
}
+ return nil
+}
+
+func (session *Session) db() *core.DB {
+ return session.engine.db
}
func (session *Session) getQueryer() core.Queryer {
if session.tx != nil {
return session.tx
}
- return session.db
+ return session.db()
}
// ContextCache enable context cache or not
@@ -155,7 +180,7 @@ func (session *Session) ContextCache(context contexts.ContextCache) *Session {
// IsClosed returns if session is closed
func (session *Session) IsClosed() bool {
- return session.db == nil
+ return session.isClosed
}
func (session *Session) resetStatement() {
@@ -264,12 +289,12 @@ func (session *Session) Cascade(trueOrFalse ...bool) *Session {
}
// MustLogSQL means record SQL or not and don't follow engine's setting
-func (session *Session) MustLogSQL(log ...bool) *Session {
+func (session *Session) MustLogSQL(logs ...bool) *Session {
var showSQL = true
- if len(log) > 0 {
- showSQL = log[0]
+ if len(logs) > 0 {
+ showSQL = logs[0]
}
- session.ctx = context.WithValue(session.ctx, "__xorm_show_sql", showSQL)
+ session.ctx = context.WithValue(session.ctx, log.SessionShowSQLKey, showSQL)
return session
}
@@ -300,17 +325,7 @@ func (session *Session) Having(conditions string) *Session {
// DB db return the wrapper of sql.DB
func (session *Session) DB() *core.DB {
- if session.db == nil {
- session.db = session.engine.DB()
- session.stmtCache = make(map[uint32]*core.Stmt, 0)
- }
- return session.db
-}
-
-func cleanupProcessorsClosures(slices *[]func(interface{})) {
- if len(*slices) > 0 {
- *slices = make([]func(interface{}), 0)
- }
+ return session.db()
}
func (session *Session) canCache() bool {
@@ -404,56 +419,17 @@ func (session *Session) row2Slice(rows *core.Rows, fields []string, bean interfa
return nil, err
}
- if b, hasBeforeSet := bean.(BeforeSetProcessor); hasBeforeSet {
- for ii, key := range fields {
- b.BeforeSet(key, Cell(scanResults[ii].(*interface{})))
- }
- }
+ executeBeforeSet(bean, fields, scanResults)
+
return scanResults, nil
}
func (session *Session) slice2Bean(scanResults []interface{}, fields []string, bean interface{}, dataStruct *reflect.Value, table *schemas.Table) (schemas.PK, error) {
defer func() {
- if b, hasAfterSet := bean.(AfterSetProcessor); hasAfterSet {
- for ii, key := range fields {
- b.AfterSet(key, Cell(scanResults[ii].(*interface{})))
- }
- }
+ executeAfterSet(bean, fields, scanResults)
}()
- // handle afterClosures
- for _, closure := range session.afterClosures {
- session.afterProcessors = append(session.afterProcessors, executedProcessor{
- fun: func(sess *Session, bean interface{}) error {
- closure(bean)
- return nil
- },
- session: session,
- bean: bean,
- })
- }
-
- if a, has := bean.(AfterLoadProcessor); has {
- session.afterProcessors = append(session.afterProcessors, executedProcessor{
- fun: func(sess *Session, bean interface{}) error {
- a.AfterLoad()
- return nil
- },
- session: session,
- bean: bean,
- })
- }
-
- if a, has := bean.(AfterLoadSessionProcessor); has {
- session.afterProcessors = append(session.afterProcessors, executedProcessor{
- fun: func(sess *Session, bean interface{}) error {
- a.AfterLoad(sess)
- return nil
- },
- session: session,
- bean: bean,
- })
- }
+ buildAfterProcessors(session, bean)
var tempMap = make(map[string]int)
var pk schemas.PK
@@ -911,7 +887,7 @@ func (session *Session) incrVersionFieldValue(fieldValue *reflect.Value) {
}
}
-// Context sets the context on this session
+// ContextHook sets the context on this session
func (session *Session) Context(ctx context.Context) *Session {
session.ctx = ctx
return session