github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/soliton/chunk/chunk_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 chunk
    15  
    16  import (
    17  	"bytes"
    18  	"fmt"
    19  	"io/ioutil"
    20  	"math"
    21  	"os"
    22  	"strconv"
    23  	"strings"
    24  	"sync"
    25  	"testing"
    26  	"time"
    27  	"unsafe"
    28  
    29  	"github.com/cznic/mathutil"
    30  	"github.com/whtcorpsinc/check"
    31  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    32  	"github.com/whtcorpsinc/milevadb/config"
    33  	"github.com/whtcorpsinc/milevadb/stochastikctx/stmtctx"
    34  	"github.com/whtcorpsinc/milevadb/types"
    35  	"github.com/whtcorpsinc/milevadb/types/json"
    36  )
    37  
    38  func TestT(t *testing.T) {
    39  	path, _ := ioutil.TemFIDelir("", "oom-use-tmp-storage")
    40  	config.UFIDelateGlobal(func(conf *config.Config) {
    41  		conf.TempStoragePath = path
    42  	})
    43  	_ = os.RemoveAll(path) // clean the uncleared temp file during the last run.
    44  	_ = os.MkdirAll(path, 0755)
    45  	check.TestingT(t)
    46  }
    47  
    48  var _ = check.Suite(&testChunkSuite{})
    49  
    50  type testChunkSuite struct{}
    51  
    52  func (s *testChunkSuite) TestChunk(c *check.C) {
    53  	numDefCauss := 6
    54  	numRows := 10
    55  	chk := newChunk(8, 8, 0, 0, 40, 0)
    56  	strFmt := "%d.12345"
    57  	for i := 0; i < numRows; i++ {
    58  		chk.AppendNull(0)
    59  		chk.AppendInt64(1, int64(i))
    60  		str := fmt.Sprintf(strFmt, i)
    61  		chk.AppendString(2, str)
    62  		chk.AppendBytes(3, []byte(str))
    63  		chk.AppendMyDecimal(4, types.NewDecFromStringForTest(str))
    64  		chk.AppendJSON(5, json.CreateBinary(str))
    65  	}
    66  	c.Assert(chk.NumDefCauss(), check.Equals, numDefCauss)
    67  	c.Assert(chk.NumRows(), check.Equals, numRows)
    68  	for i := 0; i < numRows; i++ {
    69  		event := chk.GetRow(i)
    70  		c.Assert(event.GetInt64(0), check.Equals, int64(0))
    71  		c.Assert(event.IsNull(0), check.IsTrue)
    72  		c.Assert(event.GetInt64(1), check.Equals, int64(i))
    73  		str := fmt.Sprintf(strFmt, i)
    74  		c.Assert(event.IsNull(2), check.IsFalse)
    75  		c.Assert(event.GetString(2), check.Equals, str)
    76  		c.Assert(event.IsNull(3), check.IsFalse)
    77  		c.Assert(event.GetBytes(3), check.BytesEquals, []byte(str))
    78  		c.Assert(event.IsNull(4), check.IsFalse)
    79  		c.Assert(event.GetMyDecimal(4).String(), check.Equals, str)
    80  		c.Assert(event.IsNull(5), check.IsFalse)
    81  		c.Assert(string(event.GetJSON(5).GetString()), check.Equals, str)
    82  	}
    83  
    84  	chk2 := newChunk(8, 8, 0, 0, 40, 0)
    85  	for i := 0; i < numRows; i++ {
    86  		event := chk.GetRow(i)
    87  		chk2.AppendRow(event)
    88  	}
    89  	for i := 0; i < numDefCauss; i++ {
    90  		defCaus2, defCaus1 := chk2.defCausumns[i], chk.defCausumns[i]
    91  		defCaus2.elemBuf, defCaus1.elemBuf = nil, nil
    92  		c.Assert(defCaus2, check.DeepEquals, defCaus1)
    93  	}
    94  
    95  	chk = newChunk(4, 8, 16, 16, 0, 0)
    96  	f32Val := float32(1.2)
    97  	chk.AppendFloat32(0, f32Val)
    98  	f64Val := 1.3
    99  	chk.AppendFloat64(1, f64Val)
   100  	tVal := types.TimeFromDays(1)
   101  	chk.AppendTime(2, tVal)
   102  	durVal := types.Duration{Duration: time.Hour, Fsp: 6}
   103  	chk.AppendDuration(3, durVal)
   104  	enumVal := types.Enum{Name: "abc", Value: 100}
   105  	chk.AppendEnum(4, enumVal)
   106  	setVal := types.Set{Name: "def", Value: 101}
   107  	chk.AppendSet(5, setVal)
   108  
   109  	event := chk.GetRow(0)
   110  	c.Assert(event.GetFloat32(0), check.Equals, f32Val)
   111  	c.Assert(event.GetTime(2).Compare(tVal), check.Equals, 0)
   112  	// fsp is no longer maintained in chunk
   113  	c.Assert(event.GetDuration(3, 0).Duration, check.DeepEquals, durVal.Duration)
   114  	c.Assert(event.GetEnum(4), check.DeepEquals, enumVal)
   115  	c.Assert(event.GetSet(5), check.DeepEquals, setVal)
   116  
   117  	// AppendPartialRow can be different number of defCausumns, useful for join.
   118  	chk = newChunk(8, 8)
   119  	chk2 = newChunk(8)
   120  	chk2.AppendInt64(0, 1)
   121  	chk2.AppendInt64(0, -1)
   122  	chk.AppendPartialRow(0, chk2.GetRow(0))
   123  	chk.AppendPartialRow(1, chk2.GetRow(0))
   124  	c.Assert(chk.GetRow(0).GetInt64(0), check.Equals, int64(1))
   125  	c.Assert(chk.GetRow(0).GetInt64(1), check.Equals, int64(1))
   126  	c.Assert(chk.NumRows(), check.Equals, 1)
   127  
   128  	// AppendRowByDefCausIdxs and AppendPartialRowByDefCausIdxs can do projection from event.
   129  	chk = newChunk(8, 8)
   130  	event = MutRowFromValues(0, 1, 2, 3).ToRow()
   131  	chk.AppendRowByDefCausIdxs(event, []int{3})
   132  	chk.AppendRowByDefCausIdxs(event, []int{1})
   133  	chk.AppendRowByDefCausIdxs(event, []int{})
   134  	c.Assert(chk.DeferredCauset(0).Int64s(), check.DeepEquals, []int64{3, 1})
   135  	c.Assert(chk.numVirtualRows, check.Equals, 3)
   136  	chk.AppendPartialRowByDefCausIdxs(1, event, []int{2})
   137  	chk.AppendPartialRowByDefCausIdxs(1, event, []int{0})
   138  	chk.AppendPartialRowByDefCausIdxs(0, event, []int{1, 3})
   139  	c.Assert(chk.DeferredCauset(0).Int64s(), check.DeepEquals, []int64{3, 1, 1})
   140  	c.Assert(chk.DeferredCauset(1).Int64s(), check.DeepEquals, []int64{2, 0, 3})
   141  	c.Assert(chk.numVirtualRows, check.Equals, 3)
   142  
   143  	// Test Reset.
   144  	chk = newChunk(0)
   145  	chk.AppendString(0, "abcd")
   146  	chk.Reset()
   147  	chk.AppendString(0, "def")
   148  	c.Assert(chk.GetRow(0).GetString(0), check.Equals, "def")
   149  
   150  	// Test float32
   151  	chk = newChunk(4)
   152  	chk.AppendFloat32(0, 1)
   153  	chk.AppendFloat32(0, 1)
   154  	chk.AppendFloat32(0, 1)
   155  	c.Assert(chk.GetRow(2).GetFloat32(0), check.Equals, float32(1))
   156  }
   157  
   158  func (s *testChunkSuite) TestAppend(c *check.C) {
   159  	fieldTypes := make([]*types.FieldType, 0, 3)
   160  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   161  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeVarchar})
   162  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeJSON})
   163  
   164  	jsonObj, err := json.ParseBinaryFromString("{\"k1\":\"v1\"}")
   165  	c.Assert(err, check.IsNil)
   166  
   167  	src := NewChunkWithCapacity(fieldTypes, 32)
   168  	dst := NewChunkWithCapacity(fieldTypes, 32)
   169  
   170  	src.AppendFloat32(0, 12.8)
   171  	src.AppendString(1, "abc")
   172  	src.AppendJSON(2, jsonObj)
   173  	src.AppendNull(0)
   174  	src.AppendNull(1)
   175  	src.AppendNull(2)
   176  
   177  	dst.Append(src, 0, 2)
   178  	dst.Append(src, 0, 2)
   179  	dst.Append(src, 0, 2)
   180  	dst.Append(src, 0, 2)
   181  	dst.Append(dst, 2, 6)
   182  	dst.Append(dst, 6, 6)
   183  
   184  	c.Assert(len(dst.defCausumns), check.Equals, 3)
   185  
   186  	c.Assert(dst.defCausumns[0].length, check.Equals, 12)
   187  	c.Assert(dst.defCausumns[0].nullCount(), check.Equals, 6)
   188  	c.Assert(string(dst.defCausumns[0].nullBitmap), check.Equals, string([]byte{0x55, 0x05}))
   189  	c.Assert(len(dst.defCausumns[0].offsets), check.Equals, 0)
   190  	c.Assert(len(dst.defCausumns[0].data), check.Equals, 4*12)
   191  	c.Assert(len(dst.defCausumns[0].elemBuf), check.Equals, 4)
   192  
   193  	c.Assert(dst.defCausumns[1].length, check.Equals, 12)
   194  	c.Assert(dst.defCausumns[1].nullCount(), check.Equals, 6)
   195  	c.Assert(string(dst.defCausumns[0].nullBitmap), check.Equals, string([]byte{0x55, 0x05}))
   196  	c.Assert(fmt.Sprintf("%v", dst.defCausumns[1].offsets), check.Equals, fmt.Sprintf("%v", []int64{0, 3, 3, 6, 6, 9, 9, 12, 12, 15, 15, 18, 18}))
   197  	c.Assert(string(dst.defCausumns[1].data), check.Equals, "abcabcabcabcabcabc")
   198  	c.Assert(len(dst.defCausumns[1].elemBuf), check.Equals, 0)
   199  
   200  	c.Assert(dst.defCausumns[2].length, check.Equals, 12)
   201  	c.Assert(dst.defCausumns[2].nullCount(), check.Equals, 6)
   202  	c.Assert(string(dst.defCausumns[0].nullBitmap), check.Equals, string([]byte{0x55, 0x05}))
   203  	c.Assert(len(dst.defCausumns[2].offsets), check.Equals, 13)
   204  	c.Assert(len(dst.defCausumns[2].data), check.Equals, 150)
   205  	c.Assert(len(dst.defCausumns[2].elemBuf), check.Equals, 0)
   206  	for i := 0; i < 12; i += 2 {
   207  		jsonElem := dst.GetRow(i).GetJSON(2)
   208  		cmpRes := json.CompareBinary(jsonElem, jsonObj)
   209  		c.Assert(cmpRes, check.Equals, 0)
   210  	}
   211  }
   212  
   213  func (s *testChunkSuite) TestTruncateTo(c *check.C) {
   214  	fieldTypes := make([]*types.FieldType, 0, 3)
   215  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   216  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeVarchar})
   217  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeJSON})
   218  
   219  	jsonObj, err := json.ParseBinaryFromString("{\"k1\":\"v1\"}")
   220  	c.Assert(err, check.IsNil)
   221  
   222  	src := NewChunkWithCapacity(fieldTypes, 32)
   223  
   224  	for i := 0; i < 8; i++ {
   225  		src.AppendFloat32(0, 12.8)
   226  		src.AppendString(1, "abc")
   227  		src.AppendJSON(2, jsonObj)
   228  		src.AppendNull(0)
   229  		src.AppendNull(1)
   230  		src.AppendNull(2)
   231  	}
   232  
   233  	src.TruncateTo(16)
   234  	src.TruncateTo(16)
   235  	src.TruncateTo(14)
   236  	src.TruncateTo(12)
   237  	c.Assert(len(src.defCausumns), check.Equals, 3)
   238  
   239  	c.Assert(src.defCausumns[0].length, check.Equals, 12)
   240  	c.Assert(src.defCausumns[0].nullCount(), check.Equals, 6)
   241  	c.Assert(string(src.defCausumns[0].nullBitmap), check.Equals, string([]byte{0x55, 0x05}))
   242  	c.Assert(len(src.defCausumns[0].offsets), check.Equals, 0)
   243  	c.Assert(len(src.defCausumns[0].data), check.Equals, 4*12)
   244  	c.Assert(len(src.defCausumns[0].elemBuf), check.Equals, 4)
   245  
   246  	c.Assert(src.defCausumns[1].length, check.Equals, 12)
   247  	c.Assert(src.defCausumns[1].nullCount(), check.Equals, 6)
   248  	c.Assert(string(src.defCausumns[0].nullBitmap), check.Equals, string([]byte{0x55, 0x05}))
   249  	c.Assert(fmt.Sprintf("%v", src.defCausumns[1].offsets), check.Equals, fmt.Sprintf("%v", []int64{0, 3, 3, 6, 6, 9, 9, 12, 12, 15, 15, 18, 18}))
   250  	c.Assert(string(src.defCausumns[1].data), check.Equals, "abcabcabcabcabcabc")
   251  	c.Assert(len(src.defCausumns[1].elemBuf), check.Equals, 0)
   252  
   253  	c.Assert(src.defCausumns[2].length, check.Equals, 12)
   254  	c.Assert(src.defCausumns[2].nullCount(), check.Equals, 6)
   255  	c.Assert(string(src.defCausumns[0].nullBitmap), check.Equals, string([]byte{0x55, 0x05}))
   256  	c.Assert(len(src.defCausumns[2].offsets), check.Equals, 13)
   257  	c.Assert(len(src.defCausumns[2].data), check.Equals, 150)
   258  	c.Assert(len(src.defCausumns[2].elemBuf), check.Equals, 0)
   259  	for i := 0; i < 12; i += 2 {
   260  		event := src.GetRow(i)
   261  		jsonElem := event.GetJSON(2)
   262  		cmpRes := json.CompareBinary(jsonElem, jsonObj)
   263  		c.Assert(cmpRes, check.Equals, 0)
   264  	}
   265  	chk := NewChunkWithCapacity(fieldTypes[:1], 1)
   266  	chk.AppendFloat32(0, 1.0)
   267  	chk.AppendFloat32(0, 1.0)
   268  	chk.TruncateTo(1)
   269  	chk.AppendNull(0)
   270  	c.Assert(chk.GetRow(1).IsNull(0), check.IsTrue)
   271  }
   272  
   273  func (s *testChunkSuite) TestChunkSizeControl(c *check.C) {
   274  	maxChunkSize := 10
   275  	chk := New([]*types.FieldType{types.NewFieldType(allegrosql.TypeLong)}, maxChunkSize, maxChunkSize)
   276  	c.Assert(chk.RequiredRows(), check.Equals, maxChunkSize)
   277  
   278  	for i := 0; i < maxChunkSize; i++ {
   279  		chk.AppendInt64(0, 1)
   280  	}
   281  	maxChunkSize += maxChunkSize / 3
   282  	chk.GrowAndReset(maxChunkSize)
   283  	c.Assert(chk.RequiredRows(), check.Equals, maxChunkSize)
   284  
   285  	maxChunkSize2 := maxChunkSize + maxChunkSize/3
   286  	chk2 := Renew(chk, maxChunkSize2)
   287  	c.Assert(chk2.RequiredRows(), check.Equals, maxChunkSize2)
   288  
   289  	chk.Reset()
   290  	for i := 1; i < maxChunkSize*2; i++ {
   291  		chk.SetRequiredRows(i, maxChunkSize)
   292  		c.Assert(chk.RequiredRows(), check.Equals, mathutil.Min(maxChunkSize, i))
   293  	}
   294  
   295  	chk.SetRequiredRows(1, maxChunkSize).
   296  		SetRequiredRows(2, maxChunkSize).
   297  		SetRequiredRows(3, maxChunkSize)
   298  	c.Assert(chk.RequiredRows(), check.Equals, 3)
   299  
   300  	chk.SetRequiredRows(-1, maxChunkSize)
   301  	c.Assert(chk.RequiredRows(), check.Equals, maxChunkSize)
   302  
   303  	chk.SetRequiredRows(5, maxChunkSize)
   304  	chk.AppendInt64(0, 1)
   305  	chk.AppendInt64(0, 1)
   306  	chk.AppendInt64(0, 1)
   307  	chk.AppendInt64(0, 1)
   308  	c.Assert(chk.NumRows(), check.Equals, 4)
   309  	c.Assert(chk.IsFull(), check.IsFalse)
   310  
   311  	chk.AppendInt64(0, 1)
   312  	c.Assert(chk.NumRows(), check.Equals, 5)
   313  	c.Assert(chk.IsFull(), check.IsTrue)
   314  
   315  	chk.AppendInt64(0, 1)
   316  	chk.AppendInt64(0, 1)
   317  	chk.AppendInt64(0, 1)
   318  	c.Assert(chk.NumRows(), check.Equals, 8)
   319  	c.Assert(chk.IsFull(), check.IsTrue)
   320  
   321  	chk.SetRequiredRows(maxChunkSize, maxChunkSize)
   322  	c.Assert(chk.NumRows(), check.Equals, 8)
   323  	c.Assert(chk.IsFull(), check.IsFalse)
   324  }
   325  
   326  // newChunk creates a new chunk and initialize defCausumns with element length.
   327  // 0 adds an varlen DeferredCauset, positive len add a fixed length DeferredCauset, negative len adds a interface DeferredCauset.
   328  func newChunk(elemLen ...int) *Chunk {
   329  	chk := &Chunk{}
   330  	for _, l := range elemLen {
   331  		if l > 0 {
   332  			chk.defCausumns = append(chk.defCausumns, newFixedLenDeferredCauset(l, 0))
   333  		} else {
   334  			chk.defCausumns = append(chk.defCausumns, newVarLenDeferredCauset(0, nil))
   335  		}
   336  	}
   337  	return chk
   338  }
   339  
   340  func newChunkWithInitCap(cap int, elemLen ...int) *Chunk {
   341  	chk := &Chunk{}
   342  	for _, l := range elemLen {
   343  		if l > 0 {
   344  			chk.defCausumns = append(chk.defCausumns, newFixedLenDeferredCauset(l, cap))
   345  		} else {
   346  			chk.defCausumns = append(chk.defCausumns, newVarLenDeferredCauset(cap, nil))
   347  		}
   348  	}
   349  	return chk
   350  }
   351  
   352  var allTypes = []*types.FieldType{
   353  	types.NewFieldType(allegrosql.TypeTiny),
   354  	types.NewFieldType(allegrosql.TypeShort),
   355  	types.NewFieldType(allegrosql.TypeInt24),
   356  	types.NewFieldType(allegrosql.TypeLong),
   357  	types.NewFieldType(allegrosql.TypeLonglong),
   358  	{
   359  		Tp:      allegrosql.TypeLonglong,
   360  		Flen:    types.UnspecifiedLength,
   361  		Decimal: types.UnspecifiedLength,
   362  		Flag:    allegrosql.UnsignedFlag,
   363  	},
   364  	types.NewFieldType(allegrosql.TypeYear),
   365  	types.NewFieldType(allegrosql.TypeFloat),
   366  	types.NewFieldType(allegrosql.TypeDouble),
   367  	types.NewFieldType(allegrosql.TypeString),
   368  	types.NewFieldType(allegrosql.TypeVarString),
   369  	types.NewFieldType(allegrosql.TypeVarchar),
   370  	types.NewFieldType(allegrosql.TypeBlob),
   371  	types.NewFieldType(allegrosql.TypeTinyBlob),
   372  	types.NewFieldType(allegrosql.TypeMediumBlob),
   373  	types.NewFieldType(allegrosql.TypeLongBlob),
   374  	types.NewFieldType(allegrosql.TypeDate),
   375  	types.NewFieldType(allegrosql.TypeDatetime),
   376  	types.NewFieldType(allegrosql.TypeTimestamp),
   377  	types.NewFieldType(allegrosql.TypeDuration),
   378  	types.NewFieldType(allegrosql.TypeNewDecimal),
   379  	{
   380  		Tp:      allegrosql.TypeSet,
   381  		Flen:    types.UnspecifiedLength,
   382  		Decimal: types.UnspecifiedLength,
   383  		Flag:    allegrosql.UnsignedFlag,
   384  		Elems:   []string{"a", "b"},
   385  	},
   386  	{
   387  		Tp:      allegrosql.TypeEnum,
   388  		Flen:    types.UnspecifiedLength,
   389  		Decimal: types.UnspecifiedLength,
   390  		Flag:    allegrosql.UnsignedFlag,
   391  		Elems:   []string{"a", "b"},
   392  	},
   393  	types.NewFieldType(allegrosql.TypeBit),
   394  	types.NewFieldType(allegrosql.TypeJSON),
   395  }
   396  
   397  func (s *testChunkSuite) TestCompare(c *check.C) {
   398  	chunk := NewChunkWithCapacity(allTypes, 32)
   399  	for i := 0; i < len(allTypes); i++ {
   400  		chunk.AppendNull(i)
   401  	}
   402  	for i := 0; i < len(allTypes); i++ {
   403  		switch allTypes[i].Tp {
   404  		case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong, allegrosql.TypeYear:
   405  			if allegrosql.HasUnsignedFlag(allTypes[i].Flag) {
   406  				chunk.AppendUint64(i, 0)
   407  			} else {
   408  				chunk.AppendInt64(i, -1)
   409  			}
   410  		case allegrosql.TypeFloat:
   411  			chunk.AppendFloat32(i, 0)
   412  		case allegrosql.TypeDouble:
   413  			chunk.AppendFloat64(i, 0)
   414  		case allegrosql.TypeString, allegrosql.TypeVarString, allegrosql.TypeVarchar,
   415  			allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
   416  			chunk.AppendString(i, "0")
   417  		case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp:
   418  			chunk.AppendTime(i, types.TimeFromDays(2000*365))
   419  		case allegrosql.TypeDuration:
   420  			chunk.AppendDuration(i, types.ZeroDuration)
   421  		case allegrosql.TypeNewDecimal:
   422  			chunk.AppendMyDecimal(i, types.NewDecFromInt(0))
   423  		case allegrosql.TypeSet:
   424  			chunk.AppendSet(i, types.Set{Name: "a", Value: 0})
   425  		case allegrosql.TypeEnum:
   426  			chunk.AppendEnum(i, types.Enum{Name: "a", Value: 0})
   427  		case allegrosql.TypeBit:
   428  			chunk.AppendBytes(i, []byte{0})
   429  		case allegrosql.TypeJSON:
   430  			chunk.AppendJSON(i, json.CreateBinary(int64(0)))
   431  		default:
   432  			c.FailNow()
   433  		}
   434  	}
   435  	for i := 0; i < len(allTypes); i++ {
   436  		switch allTypes[i].Tp {
   437  		case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong, allegrosql.TypeYear:
   438  			if allegrosql.HasUnsignedFlag(allTypes[i].Flag) {
   439  				chunk.AppendUint64(i, math.MaxUint64)
   440  			} else {
   441  				chunk.AppendInt64(i, 1)
   442  			}
   443  		case allegrosql.TypeFloat:
   444  			chunk.AppendFloat32(i, 1)
   445  		case allegrosql.TypeDouble:
   446  			chunk.AppendFloat64(i, 1)
   447  		case allegrosql.TypeString, allegrosql.TypeVarString, allegrosql.TypeVarchar,
   448  			allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
   449  			chunk.AppendString(i, "1")
   450  		case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp:
   451  			chunk.AppendTime(i, types.TimeFromDays(2001*365))
   452  		case allegrosql.TypeDuration:
   453  			chunk.AppendDuration(i, types.Duration{Duration: time.Second})
   454  		case allegrosql.TypeNewDecimal:
   455  			chunk.AppendMyDecimal(i, types.NewDecFromInt(1))
   456  		case allegrosql.TypeSet:
   457  			chunk.AppendSet(i, types.Set{Name: "b", Value: 1})
   458  		case allegrosql.TypeEnum:
   459  			chunk.AppendEnum(i, types.Enum{Name: "b", Value: 1})
   460  		case allegrosql.TypeBit:
   461  			chunk.AppendBytes(i, []byte{1})
   462  		case allegrosql.TypeJSON:
   463  			chunk.AppendJSON(i, json.CreateBinary(int64(1)))
   464  		default:
   465  			c.FailNow()
   466  		}
   467  	}
   468  	rowNull := chunk.GetRow(0)
   469  	rowSmall := chunk.GetRow(1)
   470  	rowBig := chunk.GetRow(2)
   471  	for i := 0; i < len(allTypes); i++ {
   472  		cmpFunc := GetCompareFunc(allTypes[i])
   473  		c.Assert(cmpFunc(rowNull, i, rowNull, i), check.Equals, 0)
   474  		c.Assert(cmpFunc(rowNull, i, rowSmall, i), check.Equals, -1)
   475  		c.Assert(cmpFunc(rowSmall, i, rowNull, i), check.Equals, 1)
   476  		c.Assert(cmpFunc(rowSmall, i, rowSmall, i), check.Equals, 0)
   477  		c.Assert(cmpFunc(rowSmall, i, rowBig, i), check.Equals, -1, check.Commentf("%d", allTypes[i].Tp))
   478  		c.Assert(cmpFunc(rowBig, i, rowSmall, i), check.Equals, 1)
   479  		c.Assert(cmpFunc(rowBig, i, rowBig, i), check.Equals, 0)
   480  	}
   481  }
   482  
   483  func (s *testChunkSuite) TestCopyTo(c *check.C) {
   484  	chunk := NewChunkWithCapacity(allTypes, 101)
   485  	for i := 0; i < len(allTypes); i++ {
   486  		chunk.AppendNull(i)
   487  	}
   488  	for k := 0; k < 100; k++ {
   489  		for i := 0; i < len(allTypes); i++ {
   490  			switch allTypes[i].Tp {
   491  			case allegrosql.TypeTiny, allegrosql.TypeShort, allegrosql.TypeInt24, allegrosql.TypeLong, allegrosql.TypeLonglong, allegrosql.TypeYear:
   492  				if allegrosql.HasUnsignedFlag(allTypes[i].Flag) {
   493  					chunk.AppendUint64(i, uint64(k))
   494  				} else {
   495  					chunk.AppendInt64(i, int64(k))
   496  				}
   497  			case allegrosql.TypeFloat:
   498  				chunk.AppendFloat32(i, float32(k))
   499  			case allegrosql.TypeDouble:
   500  				chunk.AppendFloat64(i, float64(k))
   501  			case allegrosql.TypeString, allegrosql.TypeVarString, allegrosql.TypeVarchar,
   502  				allegrosql.TypeBlob, allegrosql.TypeTinyBlob, allegrosql.TypeMediumBlob, allegrosql.TypeLongBlob:
   503  				chunk.AppendString(i, fmt.Sprintf("%v", k))
   504  			case allegrosql.TypeDate, allegrosql.TypeDatetime, allegrosql.TypeTimestamp:
   505  				chunk.AppendTime(i, types.TimeFromDays(2000*365+int64(k)))
   506  			case allegrosql.TypeDuration:
   507  				chunk.AppendDuration(i, types.Duration{Duration: time.Second * time.Duration(k), Fsp: types.DefaultFsp})
   508  			case allegrosql.TypeNewDecimal:
   509  				chunk.AppendMyDecimal(i, types.NewDecFromInt(int64(k)))
   510  			case allegrosql.TypeSet:
   511  				chunk.AppendSet(i, types.Set{Name: "a", Value: uint64(k)})
   512  			case allegrosql.TypeEnum:
   513  				chunk.AppendEnum(i, types.Enum{Name: "a", Value: uint64(k)})
   514  			case allegrosql.TypeBit:
   515  				chunk.AppendBytes(i, []byte{byte(k)})
   516  			case allegrosql.TypeJSON:
   517  				chunk.AppendJSON(i, json.CreateBinary(int64(k)))
   518  			default:
   519  				c.FailNow()
   520  			}
   521  		}
   522  	}
   523  
   524  	ck1 := chunk.CopyConstruct()
   525  
   526  	for k := 0; k < 101; k++ {
   527  		event := chunk.GetRow(k)
   528  		r1 := ck1.GetRow(k)
   529  		for i := 0; i < len(allTypes); i++ {
   530  			cmpFunc := GetCompareFunc(allTypes[i])
   531  			c.Assert(cmpFunc(event, i, r1, i), check.Equals, 0)
   532  		}
   533  
   534  	}
   535  }
   536  
   537  func (s *testChunkSuite) TestGetDecimalCauset(c *check.C) {
   538  	causet := types.NewCauset(1.01)
   539  	decType := types.NewFieldType(allegrosql.TypeNewDecimal)
   540  	decType.Flen = 4
   541  	decType.Decimal = 2
   542  	sc := new(stmtctx.StatementContext)
   543  	decCauset, err := causet.ConvertTo(sc, decType)
   544  	c.Assert(err, check.IsNil)
   545  	chk := NewChunkWithCapacity([]*types.FieldType{decType}, 32)
   546  	chk.AppendMyDecimal(0, decCauset.GetMysqlDecimal())
   547  	decFromChk := chk.GetRow(0).GetCauset(0, decType)
   548  	c.Assert(decCauset.Length(), check.Equals, decFromChk.Length())
   549  	c.Assert(decCauset.Frac(), check.Equals, decFromChk.Frac())
   550  }
   551  
   552  func (s *testChunkSuite) TestChunkMemoryUsage(c *check.C) {
   553  	fieldTypes := make([]*types.FieldType, 0, 5)
   554  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   555  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeVarchar})
   556  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeJSON})
   557  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeDatetime})
   558  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeDuration})
   559  
   560  	initCap := 10
   561  	chk := NewChunkWithCapacity(fieldTypes, initCap)
   562  
   563  	//cap(c.nullBitmap) + cap(c.offsets)*4 + cap(c.data) + cap(c.elemBuf)
   564  	defCausUsage := make([]int, len(fieldTypes))
   565  	defCausUsage[0] = (initCap+7)>>3 + 0 + initCap*4 + 4
   566  	defCausUsage[1] = (initCap+7)>>3 + (initCap+1)*4 + initCap*8 + 0
   567  	defCausUsage[2] = (initCap+7)>>3 + (initCap+1)*4 + initCap*8 + 0
   568  	defCausUsage[3] = (initCap+7)>>3 + 0 + initCap*sizeTime + sizeTime
   569  	defCausUsage[4] = (initCap+7)>>3 + 0 + initCap*8 + 8
   570  
   571  	expectedUsage := 0
   572  	for i := range defCausUsage {
   573  		expectedUsage += defCausUsage[i] + int(unsafe.Sizeof(*chk.defCausumns[i]))
   574  	}
   575  	memUsage := chk.MemoryUsage()
   576  	c.Assert(memUsage, check.Equals, int64(expectedUsage))
   577  
   578  	jsonObj, err := json.ParseBinaryFromString("1")
   579  	c.Assert(err, check.IsNil)
   580  	timeObj := types.NewTime(types.FromGoTime(time.Now()), allegrosql.TypeDatetime, 0)
   581  	durationObj := types.Duration{Duration: math.MaxInt64, Fsp: 0}
   582  
   583  	chk.AppendFloat32(0, 12.4)
   584  	chk.AppendString(1, "123")
   585  	chk.AppendJSON(2, jsonObj)
   586  	chk.AppendTime(3, timeObj)
   587  	chk.AppendDuration(4, durationObj)
   588  
   589  	memUsage = chk.MemoryUsage()
   590  	c.Assert(memUsage, check.Equals, int64(expectedUsage))
   591  
   592  	chk.AppendFloat32(0, 12.4)
   593  	chk.AppendString(1, "123111111111111111111111111111111111111111111111")
   594  	chk.AppendJSON(2, jsonObj)
   595  	chk.AppendTime(3, timeObj)
   596  	chk.AppendDuration(4, durationObj)
   597  
   598  	memUsage = chk.MemoryUsage()
   599  	defCausUsage[1] = (initCap+7)>>3 + (initCap+1)*4 + cap(chk.defCausumns[1].data) + 0
   600  	expectedUsage = 0
   601  	for i := range defCausUsage {
   602  		expectedUsage += defCausUsage[i] + int(unsafe.Sizeof(*chk.defCausumns[i]))
   603  	}
   604  	c.Assert(memUsage, check.Equals, int64(expectedUsage))
   605  }
   606  
   607  func (s *testChunkSuite) TestSwapDeferredCauset(c *check.C) {
   608  	fieldTypes := make([]*types.FieldType, 0, 2)
   609  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   610  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   611  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   612  
   613  	// chk1: defCausumn1 refers to defCausumn0
   614  	chk1 := NewChunkWithCapacity(fieldTypes, 1)
   615  	chk1.AppendFloat32(0, 1)
   616  	chk1.MakeRef(0, 1)
   617  	chk1.AppendFloat32(2, 3)
   618  
   619  	// chk2: defCausumn1 refers to defCausumn0
   620  	chk2 := NewChunkWithCapacity(fieldTypes, 1)
   621  	chk2.AppendFloat32(0, 1)
   622  	chk2.MakeRef(0, 1)
   623  	chk2.AppendFloat32(2, 3)
   624  
   625  	c.Assert(chk1.defCausumns[0] == chk1.defCausumns[1], check.IsTrue)
   626  	c.Assert(chk2.defCausumns[0] == chk2.defCausumns[1], check.IsTrue)
   627  
   628  	checkRef := func() {
   629  		c.Assert(chk1.defCausumns[0] == chk1.defCausumns[1], check.IsTrue)
   630  		c.Assert(chk1.defCausumns[0] == chk2.defCausumns[0], check.IsFalse)
   631  		c.Assert(chk2.defCausumns[0] == chk2.defCausumns[1], check.IsTrue)
   632  	}
   633  
   634  	chk1.SwapDeferredCauset(0, chk2, 0)
   635  	checkRef()
   636  
   637  	chk1.SwapDeferredCauset(0, chk2, 1)
   638  	checkRef()
   639  
   640  	chk2.SwapDeferredCauset(1, chk2, 0)
   641  	checkRef()
   642  
   643  	chk2.SwapDeferredCauset(1, chk2, 1)
   644  	checkRef()
   645  
   646  	chk2.SwapDeferredCauset(1, chk2, 2)
   647  	checkRef()
   648  
   649  	chk2.SwapDeferredCauset(2, chk2, 0)
   650  	checkRef()
   651  }
   652  
   653  func (s *testChunkSuite) TestPreAlloc4RowAndInsert(c *check.C) {
   654  	fieldTypes := make([]*types.FieldType, 0, 4)
   655  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   656  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeLonglong})
   657  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeNewDecimal})
   658  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeVarchar})
   659  
   660  	srcChk := NewChunkWithCapacity(fieldTypes, 10)
   661  	for i := int64(0); i < 10; i++ {
   662  		srcChk.AppendFloat32(0, float32(i))
   663  		srcChk.AppendInt64(1, i)
   664  		srcChk.AppendMyDecimal(2, types.NewDecFromInt(i))
   665  		srcChk.AppendString(3, strings.Repeat(strconv.FormatInt(i, 10), int(i)))
   666  	}
   667  
   668  	destChk := NewChunkWithCapacity(fieldTypes, 3)
   669  
   670  	// Test Chunk.PreAlloc.
   671  	for i := 0; i < srcChk.NumRows(); i++ {
   672  		c.Assert(destChk.NumRows(), check.Equals, i)
   673  		destChk.preAlloc(srcChk.GetRow(i))
   674  	}
   675  	for i, srcDefCaus := range srcChk.defCausumns {
   676  		destDefCaus := destChk.defCausumns[i]
   677  		c.Assert(len(srcDefCaus.elemBuf), check.Equals, len(destDefCaus.elemBuf))
   678  		c.Assert(len(srcDefCaus.data), check.Equals, len(destDefCaus.data))
   679  		c.Assert(len(srcDefCaus.offsets), check.Equals, len(destDefCaus.offsets))
   680  		c.Assert(len(srcDefCaus.nullBitmap), check.Equals, len(destDefCaus.nullBitmap))
   681  		c.Assert(srcDefCaus.length, check.Equals, destDefCaus.length)
   682  		c.Assert(srcDefCaus.nullCount(), check.Equals, destDefCaus.nullCount())
   683  
   684  		for _, val := range destDefCaus.data {
   685  			c.Assert(val == 0, check.IsTrue)
   686  		}
   687  		for j, val := range srcDefCaus.offsets {
   688  			c.Assert(val, check.Equals, destDefCaus.offsets[j])
   689  		}
   690  		for j, val := range srcDefCaus.nullBitmap {
   691  			c.Assert(val, check.Equals, destDefCaus.nullBitmap[j])
   692  		}
   693  		for _, val := range destDefCaus.elemBuf {
   694  			c.Assert(val == 0, check.IsTrue)
   695  		}
   696  	}
   697  
   698  	// Test Chunk.Insert.
   699  	for i := srcChk.NumRows() - 1; i >= 0; i-- {
   700  		destChk.insert(i, srcChk.GetRow(i))
   701  	}
   702  	for i, srcDefCaus := range srcChk.defCausumns {
   703  		destDefCaus := destChk.defCausumns[i]
   704  
   705  		for j, val := range srcDefCaus.data {
   706  			c.Assert(val, check.Equals, destDefCaus.data[j])
   707  		}
   708  		for j, val := range srcDefCaus.offsets {
   709  			c.Assert(val, check.Equals, destDefCaus.offsets[j])
   710  		}
   711  		for j, val := range srcDefCaus.nullBitmap {
   712  			c.Assert(val, check.Equals, destDefCaus.nullBitmap[j])
   713  		}
   714  		for _, val := range destDefCaus.elemBuf {
   715  			c.Assert(val == 0, check.IsTrue)
   716  		}
   717  	}
   718  
   719  	// Test parallel Chunk.Insert.
   720  	destChk.Reset()
   721  	startWg, endWg := &sync.WaitGroup{}, &sync.WaitGroup{}
   722  	startWg.Add(1)
   723  	for i := 0; i < srcChk.NumRows(); i++ {
   724  		destChk.preAlloc(srcChk.GetRow(i))
   725  		endWg.Add(1)
   726  		go func(rowIdx int) {
   727  			defer func() {
   728  				endWg.Done()
   729  			}()
   730  			startWg.Wait()
   731  			destChk.insert(rowIdx, srcChk.GetRow(rowIdx))
   732  		}(i)
   733  	}
   734  	startWg.Done()
   735  	endWg.Wait()
   736  	for i, srcDefCaus := range srcChk.defCausumns {
   737  		destDefCaus := destChk.defCausumns[i]
   738  
   739  		for j, val := range srcDefCaus.data {
   740  			c.Assert(val, check.Equals, destDefCaus.data[j])
   741  		}
   742  		for j, val := range srcDefCaus.offsets {
   743  			c.Assert(val, check.Equals, destDefCaus.offsets[j])
   744  		}
   745  		for j, val := range srcDefCaus.nullBitmap {
   746  			c.Assert(val, check.Equals, destDefCaus.nullBitmap[j])
   747  		}
   748  		for _, val := range destDefCaus.elemBuf {
   749  			c.Assert(val == 0, check.IsTrue)
   750  		}
   751  	}
   752  }
   753  
   754  func (s *testChunkSuite) TestAppendSel(c *check.C) {
   755  	tll := &types.FieldType{Tp: allegrosql.TypeLonglong}
   756  	chk := NewChunkWithCapacity([]*types.FieldType{tll}, 1024)
   757  	sel := make([]int, 0, 1024/2)
   758  	for i := 0; i < 1024/2; i++ {
   759  		chk.AppendInt64(0, int64(i))
   760  		if i%2 == 0 {
   761  			sel = append(sel, i)
   762  		}
   763  	}
   764  	chk.SetSel(sel)
   765  	c.Assert(chk.NumRows(), check.Equals, 1024/2/2)
   766  	chk.AppendInt64(0, int64(1))
   767  	c.Assert(chk.NumRows(), check.Equals, 1024/2/2+1)
   768  	sel = chk.Sel()
   769  	c.Assert(sel[len(sel)-1], check.Equals, 1024/2)
   770  }
   771  
   772  func (s *testChunkSuite) TestMakeRefTo(c *check.C) {
   773  	fieldTypes := make([]*types.FieldType, 0, 2)
   774  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   775  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   776  
   777  	chk1 := NewChunkWithCapacity(fieldTypes, 1)
   778  	chk1.AppendFloat32(0, 1)
   779  	chk1.AppendFloat32(1, 3)
   780  
   781  	chk2 := NewChunkWithCapacity(fieldTypes, 1)
   782  	chk2.MakeRefTo(0, chk1, 1)
   783  	chk2.MakeRefTo(1, chk1, 0)
   784  
   785  	c.Assert(chk2.defCausumns[0] == chk1.defCausumns[1], check.IsTrue)
   786  	c.Assert(chk2.defCausumns[1] == chk1.defCausumns[0], check.IsTrue)
   787  }
   788  
   789  func BenchmarkAppendInt(b *testing.B) {
   790  	b.ReportAllocs()
   791  	chk := newChunk(8)
   792  	for i := 0; i < b.N; i++ {
   793  		appendInt(chk)
   794  	}
   795  }
   796  
   797  func appendInt(chk *Chunk) {
   798  	chk.Reset()
   799  	for i := 0; i < 1000; i++ {
   800  		chk.AppendInt64(0, int64(i))
   801  	}
   802  }
   803  
   804  func BenchmarkAppendString(b *testing.B) {
   805  	b.ReportAllocs()
   806  	chk := newChunk(0)
   807  	for i := 0; i < b.N; i++ {
   808  		appendString(chk)
   809  	}
   810  }
   811  
   812  func appendString(chk *Chunk) {
   813  	chk.Reset()
   814  	for i := 0; i < 1000; i++ {
   815  		chk.AppendString(0, "abcd")
   816  	}
   817  }
   818  
   819  func BenchmarkAppendRow(b *testing.B) {
   820  	b.ReportAllocs()
   821  	rowChk := newChunk(8, 8, 0, 0)
   822  	rowChk.AppendNull(0)
   823  	rowChk.AppendInt64(1, 1)
   824  	rowChk.AppendString(2, "abcd")
   825  	rowChk.AppendBytes(3, []byte("abcd"))
   826  
   827  	chk := newChunk(8, 8, 0, 0)
   828  	for i := 0; i < b.N; i++ {
   829  		appendRow(chk, rowChk.GetRow(0))
   830  	}
   831  }
   832  
   833  func appendRow(chk *Chunk, event Row) {
   834  	chk.Reset()
   835  	for i := 0; i < 1000; i++ {
   836  		chk.AppendRow(event)
   837  	}
   838  }
   839  
   840  func BenchmarkAppendBytes1024(b *testing.B) {
   841  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   842  	var bs = make([]byte, 256)
   843  	for i := 0; i < b.N; i++ {
   844  		appendBytes(chk, bs, 1024)
   845  	}
   846  }
   847  
   848  func BenchmarkAppendBytes512(b *testing.B) {
   849  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   850  	var bs = make([]byte, 256)
   851  	for i := 0; i < b.N; i++ {
   852  		appendBytes(chk, bs, 512)
   853  	}
   854  }
   855  
   856  func BenchmarkAppendBytes256(b *testing.B) {
   857  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   858  	var bs = make([]byte, 256)
   859  	for i := 0; i < b.N; i++ {
   860  		appendBytes(chk, bs, 256)
   861  	}
   862  }
   863  
   864  func BenchmarkAppendBytes128(b *testing.B) {
   865  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   866  	var bs = make([]byte, 256)
   867  	for i := 0; i < b.N; i++ {
   868  		appendBytes(chk, bs, 128)
   869  	}
   870  }
   871  
   872  func BenchmarkAppendBytes64(b *testing.B) {
   873  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   874  	var bs = make([]byte, 256)
   875  	for i := 0; i < b.N; i++ {
   876  		appendBytes(chk, bs, 64)
   877  	}
   878  }
   879  
   880  func BenchmarkAppendBytes32(b *testing.B) {
   881  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   882  	var bs = make([]byte, 256)
   883  	for i := 0; i < b.N; i++ {
   884  		appendBytes(chk, bs, 32)
   885  	}
   886  }
   887  
   888  func BenchmarkAppendBytes16(b *testing.B) {
   889  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   890  	var bs = make([]byte, 256)
   891  	for i := 0; i < b.N; i++ {
   892  		appendBytes(chk, bs, 16)
   893  	}
   894  }
   895  
   896  func BenchmarkAppendBytes8(b *testing.B) {
   897  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   898  	var bs = make([]byte, 256)
   899  	for i := 0; i < b.N; i++ {
   900  		appendBytes(chk, bs, 8)
   901  	}
   902  }
   903  
   904  func BenchmarkAppendBytes4(b *testing.B) {
   905  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   906  	var bs = make([]byte, 256)
   907  	for i := 0; i < b.N; i++ {
   908  		appendBytes(chk, bs, 4)
   909  	}
   910  }
   911  
   912  func BenchmarkAppendBytes2(b *testing.B) {
   913  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   914  	var bs = make([]byte, 256)
   915  	for i := 0; i < b.N; i++ {
   916  		appendBytes(chk, bs, 2)
   917  	}
   918  }
   919  
   920  func BenchmarkAppendBytes1(b *testing.B) {
   921  	chk := NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 32)
   922  	var bs = make([]byte, 256)
   923  	for i := 0; i < b.N; i++ {
   924  		appendBytes(chk, bs, 1)
   925  	}
   926  }
   927  
   928  func appendBytes(chk *Chunk, bs []byte, times int) {
   929  	chk.Reset()
   930  	for i := 0; i < times; i++ {
   931  		chk.AppendBytes(0, bs)
   932  	}
   933  }
   934  
   935  func BenchmarkAccess(b *testing.B) {
   936  	b.StopTimer()
   937  	rowChk := newChunk(8)
   938  	for i := 0; i < 8192; i++ {
   939  		rowChk.AppendInt64(0, math.MaxUint16)
   940  	}
   941  	b.StartTimer()
   942  	var sum int64
   943  	for i := 0; i < b.N; i++ {
   944  		for j := 0; j < 8192; j++ {
   945  			sum += rowChk.GetRow(j).GetInt64(0)
   946  		}
   947  	}
   948  	fmt.Println(sum)
   949  }
   950  
   951  func BenchmarkChunkMemoryUsage(b *testing.B) {
   952  	fieldTypes := make([]*types.FieldType, 0, 4)
   953  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeFloat})
   954  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeVarchar})
   955  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeDatetime})
   956  	fieldTypes = append(fieldTypes, &types.FieldType{Tp: allegrosql.TypeDuration})
   957  
   958  	initCap := 10
   959  	chk := NewChunkWithCapacity(fieldTypes, initCap)
   960  	timeObj := types.NewTime(types.FromGoTime(time.Now()), allegrosql.TypeDatetime, 0)
   961  	durationObj := types.Duration{Duration: math.MaxInt64, Fsp: 0}
   962  
   963  	for i := 0; i < initCap; i++ {
   964  		chk.AppendFloat64(0, 123.123)
   965  		chk.AppendString(1, "123")
   966  		chk.AppendTime(2, timeObj)
   967  		chk.AppendDuration(3, durationObj)
   968  	}
   969  	b.ResetTimer()
   970  	for i := 0; i < b.N; i++ {
   971  		chk.MemoryUsage()
   972  	}
   973  }
   974  
   975  type seqNumberGenerateInterDirc struct {
   976  	seq          int
   977  	genCountSize int
   978  }
   979  
   980  func (x *seqNumberGenerateInterDirc) Next(chk *Chunk, resize bool) {
   981  	if resize {
   982  		chk.GrowAndReset(1024)
   983  	} else {
   984  		chk.Reset()
   985  	}
   986  	for chk.NumRows() < chk.Capacity() {
   987  		x.seq++
   988  		if x.seq > x.genCountSize {
   989  			break
   990  		}
   991  		chk.AppendInt64(0, 1)
   992  	}
   993  }
   994  
   995  type benchChunkGrowCase struct {
   996  	tag        string
   997  	reuse      bool
   998  	newReset   bool
   999  	cntPerCall int
  1000  	initCap    int
  1001  	maxCap     int
  1002  }
  1003  
  1004  func (b *benchChunkGrowCase) String() string {
  1005  	var buff bytes.Buffer
  1006  	if b.reuse {
  1007  		buff.WriteString("renew,")
  1008  	} else {
  1009  		buff.WriteString("reset,")
  1010  	}
  1011  	buff.WriteString("cntPerCall:" + strconv.Itoa(b.cntPerCall) + ",")
  1012  	buff.WriteString("cap from:" + strconv.Itoa(b.initCap) + " to " + strconv.Itoa(b.maxCap) + ",")
  1013  	if b.tag != "" {
  1014  		buff.WriteString("[" + b.tag + "]")
  1015  	}
  1016  	return buff.String()
  1017  }
  1018  
  1019  func BenchmarkChunkGrowSuit(b *testing.B) {
  1020  	tests := []benchChunkGrowCase{
  1021  		{reuse: true, newReset: false, cntPerCall: 10000000, initCap: 1024, maxCap: 1024},
  1022  		{reuse: true, newReset: false, cntPerCall: 10000000, initCap: 32, maxCap: 32},
  1023  		{reuse: true, newReset: true, cntPerCall: 10000000, initCap: 32, maxCap: 1024, tag: "grow"},
  1024  		{reuse: false, newReset: false, cntPerCall: 10000000, initCap: 1024, maxCap: 1024},
  1025  		{reuse: false, newReset: false, cntPerCall: 10000000, initCap: 32, maxCap: 32},
  1026  		{reuse: false, newReset: true, cntPerCall: 10000000, initCap: 32, maxCap: 1024, tag: "grow"},
  1027  		{reuse: true, newReset: false, cntPerCall: 10, initCap: 1024, maxCap: 1024},
  1028  		{reuse: true, newReset: false, cntPerCall: 10, initCap: 32, maxCap: 32},
  1029  		{reuse: true, newReset: true, cntPerCall: 10, initCap: 32, maxCap: 1024, tag: "grow"},
  1030  		{reuse: false, newReset: false, cntPerCall: 10, initCap: 1024, maxCap: 1024},
  1031  		{reuse: false, newReset: false, cntPerCall: 10, initCap: 32, maxCap: 32},
  1032  		{reuse: false, newReset: true, cntPerCall: 10, initCap: 32, maxCap: 1024, tag: "grow"},
  1033  	}
  1034  	for _, test := range tests {
  1035  		b.Run(test.String(), benchmarkChunkGrow(test))
  1036  	}
  1037  }
  1038  
  1039  func benchmarkChunkGrow(t benchChunkGrowCase) func(b *testing.B) {
  1040  	return func(b *testing.B) {
  1041  		b.ReportAllocs()
  1042  		chk := New([]*types.FieldType{{Tp: allegrosql.TypeLong}}, t.initCap, t.maxCap)
  1043  		b.ResetTimer()
  1044  		for i := 0; i < b.N; i++ {
  1045  			e := &seqNumberGenerateInterDirc{genCountSize: t.cntPerCall}
  1046  			for {
  1047  				e.Next(chk, t.newReset)
  1048  				if chk.NumRows() == 0 {
  1049  					break
  1050  				}
  1051  				if !t.reuse {
  1052  					if t.newReset {
  1053  						chk = Renew(chk, t.maxCap)
  1054  					} else {
  1055  						chk = New([]*types.FieldType{{Tp: allegrosql.TypeLong}}, t.initCap, t.maxCap)
  1056  					}
  1057  				}
  1058  			}
  1059  		}
  1060  	}
  1061  }