github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/causetstore/milevadb-server/einsteindb/scan_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, 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 einsteindb
    15  
    16  import (
    17  	"bytes"
    18  	"context"
    19  	"fmt"
    20  
    21  	. "github.com/whtcorpsinc/check"
    22  	"github.com/whtcorpsinc/milevadb/blockcodec"
    23  	"github.com/whtcorpsinc/milevadb/ekv"
    24  	"github.com/whtcorpsinc/milevadb/soliton/logutil"
    25  	"github.com/whtcorpsinc/milevadb/soliton/rowcodec"
    26  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    27  	"go.uber.org/zap"
    28  )
    29  
    30  type testScanSuite struct {
    31  	OneByOneSuite
    32  	causetstore  *einsteindbStore
    33  	recordPrefix []byte
    34  	rowNums      []int
    35  	ctx          context.Context
    36  }
    37  
    38  var _ = SerialSuites(&testScanSuite{})
    39  
    40  func (s *testScanSuite) SetUpSuite(c *C) {
    41  	s.OneByOneSuite.SetUpSuite(c)
    42  	s.causetstore = NewTestStore(c).(*einsteindbStore)
    43  	s.recordPrefix = blockcodec.GenTableRecordPrefix(1)
    44  	s.rowNums = append(s.rowNums, 1, scanBatchSize, scanBatchSize+1, scanBatchSize*3)
    45  	// Avoid using async commit logic.
    46  	s.ctx = context.WithValue(context.Background(), stochastikctx.ConnID, uint64(0))
    47  }
    48  
    49  func (s *testScanSuite) TearDownSuite(c *C) {
    50  	txn := s.beginTxn(c)
    51  	scanner, err := txn.Iter(s.recordPrefix, nil)
    52  	c.Assert(err, IsNil)
    53  	c.Assert(scanner, NotNil)
    54  	for scanner.Valid() {
    55  		k := scanner.Key()
    56  		err = txn.Delete(k)
    57  		c.Assert(err, IsNil)
    58  		scanner.Next()
    59  	}
    60  	err = txn.Commit(s.ctx)
    61  	c.Assert(err, IsNil)
    62  	err = s.causetstore.Close()
    63  	c.Assert(err, IsNil)
    64  	s.OneByOneSuite.TearDownSuite(c)
    65  }
    66  
    67  func (s *testScanSuite) beginTxn(c *C) *einsteindbTxn {
    68  	txn, err := s.causetstore.Begin()
    69  	c.Assert(err, IsNil)
    70  	return txn.(*einsteindbTxn)
    71  }
    72  
    73  func (s *testScanSuite) TestScan(c *C) {
    74  	check := func(c *C, scan ekv.Iterator, rowNum int, keyOnly bool) {
    75  		for i := 0; i < rowNum; i++ {
    76  			k := scan.Key()
    77  			expectedKey := blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(i))
    78  			if ok := bytes.Equal([]byte(k), []byte(expectedKey)); !ok {
    79  				logutil.BgLogger().Error("bytes equal check fail",
    80  					zap.Int("i", i),
    81  					zap.Int("rowNum", rowNum),
    82  					zap.Stringer("obtained key", k),
    83  					zap.Stringer("obtained val", ekv.Key(scan.Value())),
    84  					zap.Stringer("expected", expectedKey),
    85  					zap.Bool("keyOnly", keyOnly))
    86  			}
    87  			c.Assert([]byte(k), BytesEquals, []byte(expectedKey))
    88  			if !keyOnly {
    89  				v := scan.Value()
    90  				c.Assert(v, BytesEquals, genValueBytes(i))
    91  			}
    92  			// Because newScan return first item without calling scan.Next() just like go-hbase,
    93  			// for-loop count will decrease 1.
    94  			if i < rowNum-1 {
    95  				scan.Next()
    96  			}
    97  		}
    98  		scan.Next()
    99  		c.Assert(scan.Valid(), IsFalse)
   100  	}
   101  
   102  	for _, rowNum := range s.rowNums {
   103  		txn := s.beginTxn(c)
   104  		for i := 0; i < rowNum; i++ {
   105  			err := txn.Set(blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(i)), genValueBytes(i))
   106  			c.Assert(err, IsNil)
   107  		}
   108  		err := txn.Commit(s.ctx)
   109  		c.Assert(err, IsNil)
   110  		mockTableID := int64(999)
   111  		if rowNum > 123 {
   112  			_, err = s.causetstore.SplitRegions(s.ctx, [][]byte{blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(123))}, false, &mockTableID)
   113  			c.Assert(err, IsNil)
   114  		}
   115  
   116  		if rowNum > 456 {
   117  			_, err = s.causetstore.SplitRegions(s.ctx, [][]byte{blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(456))}, false, &mockTableID)
   118  			c.Assert(err, IsNil)
   119  		}
   120  
   121  		txn2 := s.beginTxn(c)
   122  		val, err := txn2.Get(context.TODO(), blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(0)))
   123  		c.Assert(err, IsNil)
   124  		c.Assert(val, BytesEquals, genValueBytes(0))
   125  		// Test scan without upperBound
   126  		scan, err := txn2.Iter(s.recordPrefix, nil)
   127  		c.Assert(err, IsNil)
   128  		check(c, scan, rowNum, false)
   129  		// Test scan with upperBound
   130  		upperBound := rowNum / 2
   131  		scan, err = txn2.Iter(s.recordPrefix, blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(upperBound)))
   132  		c.Assert(err, IsNil)
   133  		check(c, scan, upperBound, false)
   134  
   135  		txn3 := s.beginTxn(c)
   136  		txn3.SetOption(ekv.KeyOnly, true)
   137  		// Test scan without upper bound
   138  		scan, err = txn3.Iter(s.recordPrefix, nil)
   139  		c.Assert(err, IsNil)
   140  		check(c, scan, rowNum, true)
   141  		// test scan with upper bound
   142  		scan, err = txn3.Iter(s.recordPrefix, blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(upperBound)))
   143  		c.Assert(err, IsNil)
   144  		check(c, scan, upperBound, true)
   145  
   146  		// Restore KeyOnly to false
   147  		txn3.SetOption(ekv.KeyOnly, false)
   148  		scan, err = txn3.Iter(s.recordPrefix, nil)
   149  		c.Assert(err, IsNil)
   150  		check(c, scan, rowNum, true)
   151  		// test scan with upper bound
   152  		scan, err = txn3.Iter(s.recordPrefix, blockcodec.EncodeRecordKey(s.recordPrefix, ekv.IntHandle(upperBound)))
   153  		c.Assert(err, IsNil)
   154  		check(c, scan, upperBound, true)
   155  	}
   156  }
   157  
   158  func genValueBytes(i int) []byte {
   159  	var res = []byte{rowcodec.CodecVer}
   160  	res = append(res, []byte(fmt.Sprintf("%d", i))...)
   161  	return res
   162  }