github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/sessionctx/variable/session.go (about) 1 // Copyright 2015 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package variable 15 16 import ( 17 "github.com/insionng/yougam/libraries/pingcap/tidb/context" 18 "github.com/insionng/yougam/libraries/pingcap/tidb/terror" 19 ) 20 21 const codeCantGetValidID terror.ErrCode = 1 22 23 var errCantGetValidID = terror.ClassVariable.New(codeCantGetValidID, "cannot get valid auto-increment id in retry") 24 25 // RetryInfo saves retry information. 26 type RetryInfo struct { 27 Retrying bool 28 currRetryOff int 29 autoIncrementIDs []int64 30 } 31 32 // Clean does some clean work. 33 func (r *RetryInfo) Clean() { 34 r.currRetryOff = 0 35 if len(r.autoIncrementIDs) > 0 { 36 r.autoIncrementIDs = r.autoIncrementIDs[:0] 37 } 38 } 39 40 // AddAutoIncrementID adds id to AutoIncrementIDs. 41 func (r *RetryInfo) AddAutoIncrementID(id int64) { 42 r.autoIncrementIDs = append(r.autoIncrementIDs, id) 43 } 44 45 // ResetOffset resets the current retry offset. 46 func (r *RetryInfo) ResetOffset() { 47 r.currRetryOff = 0 48 } 49 50 // GetCurrAutoIncrementID gets current AutoIncrementID. 51 func (r *RetryInfo) GetCurrAutoIncrementID() (int64, error) { 52 if r.currRetryOff >= len(r.autoIncrementIDs) { 53 return 0, errCantGetValidID 54 } 55 id := r.autoIncrementIDs[r.currRetryOff] 56 r.currRetryOff++ 57 58 return id, nil 59 } 60 61 // SessionVars is to handle user-defined or global variables in current session. 62 type SessionVars struct { 63 // user-defined variables 64 Users map[string]string 65 // system variables 66 Systems map[string]string 67 // prepared statement 68 PreparedStmts map[uint32]interface{} 69 PreparedStmtNameToID map[string]uint32 70 // prepared statement auto increment id 71 preparedStmtID uint32 72 73 // retry information 74 RetryInfo *RetryInfo 75 76 // following variables are special for current session 77 Status uint16 78 LastInsertID uint64 79 AffectedRows uint64 80 81 // Client capability 82 ClientCapability uint32 83 84 // Connection ID 85 ConnectionID uint64 86 87 // Found rows 88 FoundRows uint64 89 90 // Current user 91 User string 92 } 93 94 // sessionVarsKeyType is a dummy type to avoid naming collision in context. 95 type sessionVarsKeyType int 96 97 // String defines a Stringer function for debugging and pretty printing. 98 func (k sessionVarsKeyType) String() string { 99 return "session_vars" 100 } 101 102 const sessionVarsKey sessionVarsKeyType = 0 103 104 // BindSessionVars creates a session vars object and binds it to context. 105 func BindSessionVars(ctx context.Context) { 106 v := &SessionVars{ 107 Users: make(map[string]string), 108 Systems: make(map[string]string), 109 PreparedStmts: make(map[uint32]interface{}), 110 PreparedStmtNameToID: make(map[string]uint32), 111 RetryInfo: &RetryInfo{}, 112 } 113 114 ctx.SetValue(sessionVarsKey, v) 115 } 116 117 // GetSessionVars gets the session vars from context. 118 func GetSessionVars(ctx context.Context) *SessionVars { 119 v, ok := ctx.Value(sessionVarsKey).(*SessionVars) 120 if !ok { 121 return nil 122 } 123 return v 124 } 125 126 const ( 127 characterSetConnection = "character_set_connection" 128 collationConnection = "collation_connection" 129 ) 130 131 // GetCharsetInfo gets charset and collation for current context. 132 // What character set should the server translate a statement to after receiving it? 133 // For this, the server uses the character_set_connection and collation_connection system variables. 134 // It converts statements sent by the client from character_set_client to character_set_connection 135 // (except for string literals that have an introducer such as _latin1 or _utf8). 136 // collation_connection is important for comparisons of literal strings. 137 // For comparisons of strings with column values, collation_connection does not matter because columns 138 // have their own collation, which has a higher collation precedence. 139 // See: https://dev.mysql.com/doc/refman/5.7/en/charset-connection.html 140 func GetCharsetInfo(ctx context.Context) (charset, collation string) { 141 sessionVars := GetSessionVars(ctx) 142 charset = sessionVars.Systems[characterSetConnection] 143 collation = sessionVars.Systems[collationConnection] 144 return 145 } 146 147 // SetLastInsertID saves the last insert id to the session context. 148 // TODO: we may store the result for last_insert_id sys var later. 149 func (s *SessionVars) SetLastInsertID(insertID uint64) { 150 s.LastInsertID = insertID 151 } 152 153 // SetAffectedRows saves the affected rows to the session context. 154 func (s *SessionVars) SetAffectedRows(affectedRows uint64) { 155 s.AffectedRows = affectedRows 156 } 157 158 // AddAffectedRows adds affected rows with the argument rows. 159 func (s *SessionVars) AddAffectedRows(rows uint64) { 160 s.AffectedRows += rows 161 } 162 163 // AddFoundRows adds found rows with the argument rows. 164 func (s *SessionVars) AddFoundRows(rows uint64) { 165 s.FoundRows += rows 166 } 167 168 // SetStatusFlag sets the session server status variable. 169 // If on is ture sets the flag in session status, 170 // otherwise removes the flag. 171 func (s *SessionVars) SetStatusFlag(flag uint16, on bool) { 172 if on { 173 s.Status |= flag 174 return 175 } 176 s.Status &= (^flag) 177 } 178 179 // GetNextPreparedStmtID generates and returns the next session scope prepared statement id. 180 func (s *SessionVars) GetNextPreparedStmtID() uint32 { 181 s.preparedStmtID++ 182 return s.preparedStmtID 183 } 184 185 // SetCurrentUser saves the current user to the session context. 186 func (s *SessionVars) SetCurrentUser(user string) { 187 s.User = user 188 }