github.com/pingcap/tidb-lightning@v5.0.0-rc.0.20210428090220-84b649866577+incompatible/lightning/backend/session.go (about) 1 // Copyright 2019 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 backend 15 16 import ( 17 "context" 18 "errors" 19 "fmt" 20 "strconv" 21 22 "github.com/pingcap/parser/model" 23 "github.com/pingcap/parser/mysql" 24 "github.com/pingcap/tidb/kv" 25 "github.com/pingcap/tidb/sessionctx" 26 "github.com/pingcap/tidb/sessionctx/variable" 27 28 "github.com/pingcap/tidb-lightning/lightning/common" 29 ) 30 31 // invalidIterator is a trimmed down Iterator type which is invalid. 32 type invalidIterator struct { 33 kv.Iterator 34 } 35 36 // Valid implements the kv.Iterator interface 37 func (*invalidIterator) Valid() bool { 38 return false 39 } 40 41 // Close implements the kv.Iterator interface 42 func (*invalidIterator) Close() { 43 } 44 45 type kvMemBuf struct { 46 kv.MemBuffer 47 kvPairs []common.KvPair 48 size int 49 } 50 51 func (mb *kvMemBuf) Set(k kv.Key, v []byte) error { 52 mb.kvPairs = append(mb.kvPairs, common.KvPair{ 53 Key: k.Clone(), 54 Val: append([]byte{}, v...), 55 }) 56 mb.size += len(k) + len(v) 57 return nil 58 } 59 60 func (mb *kvMemBuf) SetWithFlags(k kv.Key, v []byte, ops ...kv.FlagsOp) error { 61 return mb.Set(k, v) 62 } 63 64 func (mb *kvMemBuf) Delete(k kv.Key) error { 65 return errors.New("unsupported operation") 66 } 67 68 // Release publish all modifications in the latest staging buffer to upper level. 69 func (mb *kvMemBuf) Release(h kv.StagingHandle) { 70 } 71 72 func (mb *kvMemBuf) Staging() kv.StagingHandle { 73 return 0 74 } 75 76 // Cleanup cleanup the resources referenced by the StagingHandle. 77 // If the changes are not published by `Release`, they will be discarded. 78 func (mb *kvMemBuf) Cleanup(h kv.StagingHandle) {} 79 80 // Size returns sum of keys and values length. 81 func (mb *kvMemBuf) Size() int { 82 return mb.size 83 } 84 85 // Len returns the number of entries in the DB. 86 func (t *transaction) Len() int { 87 return t.GetMemBuffer().Len() 88 } 89 90 type kvUnionStore struct { 91 kvMemBuf 92 kv.UnionStore 93 } 94 95 func (s *kvUnionStore) GetMemBuffer() kv.MemBuffer { 96 return &s.kvMemBuf 97 } 98 99 func (s *kvUnionStore) GetIndexName(tableID, indexID int64) string { 100 panic("Unsupported Operation") 101 } 102 103 func (s *kvUnionStore) CacheIndexName(tableID, indexID int64, name string) { 104 } 105 106 func (s *kvUnionStore) CacheTableInfo(id int64, info *model.TableInfo) { 107 } 108 109 // transaction is a trimmed down Transaction type which only supports adding a 110 // new KV pair. 111 type transaction struct { 112 kv.Transaction 113 kvUnionStore 114 } 115 116 func NewTransaction() *transaction { 117 return &transaction{ 118 kvUnionStore: kvUnionStore{}, 119 } 120 } 121 122 func (t *transaction) GetMemBuffer() kv.MemBuffer { 123 return &t.kvUnionStore.kvMemBuf 124 } 125 126 func (t *transaction) Discard() { 127 // do nothing 128 } 129 130 func (t *transaction) Flush() (int, error) { 131 // do nothing 132 return 0, nil 133 } 134 135 // Reset implements the kv.MemBuffer interface 136 func (t *transaction) Reset() {} 137 138 // Get implements the kv.Retriever interface 139 func (t *transaction) Get(ctx context.Context, key kv.Key) ([]byte, error) { 140 return nil, kv.ErrNotExist 141 } 142 143 // Iter implements the kv.Retriever interface 144 func (t *transaction) Iter(k kv.Key, upperBound kv.Key) (kv.Iterator, error) { 145 return &invalidIterator{}, nil 146 } 147 148 // Set implements the kv.Mutator interface 149 func (t *transaction) Set(k kv.Key, v []byte) error { 150 return t.kvMemBuf.Set(k, v) 151 } 152 153 // SetOption implements the kv.Transaction interface 154 func (t *transaction) SetOption(opt kv.Option, val interface{}) {} 155 156 // DelOption implements the kv.Transaction interface 157 func (t *transaction) DelOption(kv.Option) {} 158 159 // SetAssertion implements the kv.Transaction interface 160 func (t *transaction) SetAssertion(kv.Key, kv.AssertionType) {} 161 162 func (t *transaction) GetUnionStore() kv.UnionStore { 163 return &t.kvUnionStore 164 } 165 166 // session is a trimmed down Session type which only wraps our own trimmed-down 167 // transaction type and provides the session variables to the TiDB library 168 // optimized for Lightning. 169 type session struct { 170 sessionctx.Context 171 txn transaction 172 vars *variable.SessionVars 173 // currently, we only set `CommonAddRecordCtx` 174 values map[fmt.Stringer]interface{} 175 } 176 177 // SessionOptions is the initial configuration of the session. 178 type SessionOptions struct { 179 SQLMode mysql.SQLMode 180 Timestamp int64 181 SysVars map[string]string 182 // a seed used for tableKvEncoder's auto random bits value 183 AutoRandomSeed int64 184 } 185 186 func newSession(options *SessionOptions) *session { 187 sqlMode := options.SQLMode 188 vars := variable.NewSessionVars() 189 vars.SkipUTF8Check = true 190 vars.StmtCtx.InInsertStmt = true 191 vars.StmtCtx.BatchCheck = true 192 vars.StmtCtx.BadNullAsWarning = !sqlMode.HasStrictMode() 193 vars.StmtCtx.TruncateAsWarning = !sqlMode.HasStrictMode() 194 vars.StmtCtx.OverflowAsWarning = !sqlMode.HasStrictMode() 195 vars.StmtCtx.AllowInvalidDate = sqlMode.HasAllowInvalidDatesMode() 196 vars.StmtCtx.IgnoreZeroInDate = !sqlMode.HasStrictMode() || sqlMode.HasAllowInvalidDatesMode() 197 if options.SysVars != nil { 198 for k, v := range options.SysVars { 199 vars.SetSystemVar(k, v) 200 } 201 } 202 vars.StmtCtx.TimeZone = vars.Location() 203 vars.SetSystemVar("timestamp", strconv.FormatInt(options.Timestamp, 10)) 204 vars.TxnCtx = nil 205 206 s := &session{ 207 vars: vars, 208 values: make(map[fmt.Stringer]interface{}, 1), 209 } 210 211 return s 212 } 213 214 func (se *session) takeKvPairs() []common.KvPair { 215 pairs := se.txn.kvMemBuf.kvPairs 216 se.txn.kvMemBuf.kvPairs = make([]common.KvPair, 0, len(pairs)) 217 se.txn.kvMemBuf.size = 0 218 return pairs 219 } 220 221 // Txn implements the sessionctx.Context interface 222 func (se *session) Txn(active bool) (kv.Transaction, error) { 223 return &se.txn, nil 224 } 225 226 // GetSessionVars implements the sessionctx.Context interface 227 func (se *session) GetSessionVars() *variable.SessionVars { 228 return se.vars 229 } 230 231 // SetValue saves a value associated with this context for key. 232 func (se *session) SetValue(key fmt.Stringer, value interface{}) { 233 se.values[key] = value 234 } 235 236 // Value returns the value associated with this context for key. 237 func (se *session) Value(key fmt.Stringer) interface{} { 238 return se.values[key] 239 } 240 241 // StmtAddDirtyTableOP implements the sessionctx.Context interface 242 func (se *session) StmtAddDirtyTableOP(op int, physicalID int64, handle kv.Handle) {}