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) {}