github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_cast_vec_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 memex
    15  
    16  import (
    17  	"math"
    18  	"math/rand"
    19  	"testing"
    20  	"time"
    21  
    22  	. "github.com/whtcorpsinc/check"
    23  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    24  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    25  	"github.com/whtcorpsinc/milevadb/types"
    26  	"github.com/whtcorpsinc/milevadb/types/json"
    27  	"github.com/whtcorpsinc/milevadb/soliton/chunk"
    28  	"github.com/whtcorpsinc/milevadb/soliton/mock"
    29  )
    30  
    31  var vecBuiltinCastCases = map[string][]vecExprBenchCase{
    32  	ast.Cast: {
    33  		{retEvalType: types.ETDecimal, childrenTypes: []types.EvalType{types.ETJson}, geners: []dataGenerator{newDecimalJSONGener(0)}},
    34  		{retEvalType: types.ETDecimal, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{newDecimalStringGener()}},
    35  		{retEvalType: types.ETDecimal, childrenTypes: []types.EvalType{types.ETReal}},
    36  		{retEvalType: types.ETDecimal, childrenTypes: []types.EvalType{types.ETDuration}},
    37  		{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETInt}},
    38  		{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETReal}},
    39  		{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDecimal}},
    40  		{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETJson}},
    41  		{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDatetime}},
    42  		{retEvalType: types.ETInt, childrenTypes: []types.EvalType{types.ETDuration}},
    43  		{
    44  			retEvalType:   types.ETInt,
    45  			childrenTypes: []types.EvalType{types.ETString},
    46  			geners:        []dataGenerator{&numStrGener{*newRangeInt64Gener(math.MinInt64+1, 0)}},
    47  		},
    48  		{
    49  			retEvalType:   types.ETInt,
    50  			childrenTypes: []types.EvalType{types.ETString},
    51  			geners:        []dataGenerator{&numStrGener{*newRangeInt64Gener(0, math.MaxInt64)}},
    52  		},
    53  		{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETInt}},
    54  		{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETInt}, geners: []dataGenerator{newRandDurInt()}},
    55  		{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETReal}, geners: []dataGenerator{newRandDurReal()}},
    56  		{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDecimal}, geners: []dataGenerator{newRandDurDecimal()}},
    57  		{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETReal}},
    58  		{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETJson}},
    59  		{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETDecimal}},
    60  		{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{newRealStringGener()}},
    61  		{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETDatetime}},
    62  		{retEvalType: types.ETReal, childrenTypes: []types.EvalType{types.ETDuration}, geners: []dataGenerator{newRangeDurationGener(0.5)}},
    63  		{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDatetime},
    64  			geners: []dataGenerator{&dateTimeGenerWithFsp{
    65  				defaultGener: *newDefaultGener(0.2, types.ETDatetime),
    66  				fsp:          1,
    67  			}},
    68  		},
    69  		{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETInt}},
    70  		{retEvalType: types.ETDecimal, childrenTypes: []types.EvalType{types.ETDatetime}},
    71  		{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETString}},
    72  		{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETDuration}},
    73  		{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETDatetime}},
    74  		{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETTimestamp}},
    75  		{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETReal}},
    76  		{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETJson}},
    77  		{retEvalType: types.ETString, childrenTypes: []types.EvalType{types.ETDecimal}},
    78  		{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETJson}, geners: []dataGenerator{&randJSONDuration{}}},
    79  		{retEvalType: types.ETDuration, childrenTypes: []types.EvalType{types.ETDuration}},
    80  		{retEvalType: types.ETJson, childrenTypes: []types.EvalType{types.ETInt}},
    81  		{retEvalType: types.ETJson, childrenTypes: []types.EvalType{types.ETReal}},
    82  		{retEvalType: types.ETJson, childrenTypes: []types.EvalType{types.ETDuration}},
    83  		{retEvalType: types.ETJson, childrenTypes: []types.EvalType{types.ETDatetime}},
    84  		{retEvalType: types.ETJson, childrenTypes: []types.EvalType{types.ETJson}},
    85  		{retEvalType: types.ETJson, childrenTypes: []types.EvalType{types.ETString}, geners: []dataGenerator{newJSONStringGener()}},
    86  		{retEvalType: types.ETJson, childrenTypes: []types.EvalType{types.ETDecimal}},
    87  		{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETJson}, geners: []dataGenerator{&datetimeJSONGener{}}},
    88  		{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETReal}},
    89  		{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETDecimal}},
    90  		{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETInt}},
    91  		{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETString},
    92  			geners: []dataGenerator{
    93  				&dateTimeStrGener{randGen: newDefaultRandGen()},
    94  				&dateStrGener{randGen: newDefaultRandGen()},
    95  				&timeStrGener{randGen: newDefaultRandGen()},
    96  			}},
    97  		{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETDuration}},
    98  		{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETDatetime}},
    99  		{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETTimestamp}},
   100  		{retEvalType: types.ETDatetime, childrenTypes: []types.EvalType{types.ETJson},
   101  			geners: []dataGenerator{
   102  				newJSONTimeGener(),
   103  			}},
   104  		{retEvalType: types.ETDecimal, childrenTypes: []types.EvalType{types.ETDecimal}},
   105  		{retEvalType: types.ETDecimal, childrenTypes: []types.EvalType{types.ETInt}},
   106  	},
   107  }
   108  
   109  type dateTimeGenerWithFsp struct {
   110  	defaultGener
   111  	fsp int8
   112  }
   113  
   114  func (g *dateTimeGenerWithFsp) gen() interface{} {
   115  	result := g.defaultGener.gen()
   116  	if t, ok := result.(types.Time); ok {
   117  		t.SetFsp(g.fsp)
   118  		return t
   119  	}
   120  	return result
   121  }
   122  
   123  type randJSONDuration struct{}
   124  
   125  func (g *randJSONDuration) gen() interface{} {
   126  	d := types.Duration{
   127  		Duration: time.Duration(rand.Intn(12))*time.Hour + time.Duration(rand.Intn(60))*time.Minute + time.Duration(rand.Intn(60))*time.Second + time.Duration(rand.Intn(1000))*time.Millisecond,
   128  		Fsp:      3}
   129  	return json.CreateBinary(d.String())
   130  }
   131  
   132  type datetimeJSONGener struct{}
   133  
   134  func (g *datetimeJSONGener) gen() interface{} {
   135  	year := rand.Intn(2200)
   136  	month := rand.Intn(10) + 1
   137  	day := rand.Intn(20) + 1
   138  	hour := rand.Intn(12)
   139  	minute := rand.Intn(60)
   140  	second := rand.Intn(60)
   141  	microsecond := rand.Intn(1000000)
   142  	d := types.NewTime(
   143  		types.FromDate(year, month, day, hour, minute, second, microsecond),
   144  		0,
   145  		3,
   146  	)
   147  	return json.CreateBinary(d.String())
   148  }
   149  
   150  func (s *testEvaluatorSuite) TestVectorizedBuiltinCastEvalOneVec(c *C) {
   151  	testVectorizedEvalOneVec(c, vecBuiltinCastCases)
   152  }
   153  
   154  func (s *testEvaluatorSuite) TestVectorizedBuiltinCastFunc(c *C) {
   155  	testVectorizedBuiltinFunc(c, vecBuiltinCastCases)
   156  }
   157  
   158  func (s *testEvaluatorSuite) TestVectorizedCastRealAsTime(c *C) {
   159  	defCaus := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDouble), Index: 0}
   160  	baseFunc, err := newBaseBuiltinFunc(mock.NewContext(), "", []Expression{defCaus}, 0)
   161  	if err != nil {
   162  		panic(err)
   163  	}
   164  	cast := &builtinCastRealAsTimeSig{baseFunc}
   165  
   166  	inputs := []*chunk.Chunk{
   167  		genCastRealAsTime(),
   168  	}
   169  
   170  	for _, input := range inputs {
   171  		result := chunk.NewDeferredCauset(types.NewFieldType(allegrosql.TypeDatetime), input.NumEvents())
   172  		c.Assert(cast.vecEvalTime(input, result), IsNil)
   173  		for i := 0; i < input.NumEvents(); i++ {
   174  			res, isNull, err := cast.evalTime(input.GetEvent(i))
   175  			c.Assert(err, IsNil)
   176  			if isNull {
   177  				c.Assert(result.IsNull(i), IsTrue)
   178  				continue
   179  			}
   180  			c.Assert(result.IsNull(i), IsFalse)
   181  			c.Assert(result.GetTime(i).Compare(res), Equals, 0)
   182  		}
   183  	}
   184  }
   185  
   186  func genCastRealAsTime() *chunk.Chunk {
   187  	input := chunk.NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeDouble)}, 10)
   188  	gen := newDefaultRandGen()
   189  	for i := 0; i < 10; i++ {
   190  		if i < 5 {
   191  			input.AppendFloat64(0, 0)
   192  		} else {
   193  			input.AppendFloat64(0, gen.Float64()*100000)
   194  		}
   195  	}
   196  	return input
   197  }
   198  
   199  // for issue https://github.com/whtcorpsinc/milevadb/issues/16825
   200  func (s *testEvaluatorSuite) TestVectorizedCastStringAsDecimalWithUnsignedFlagInUnion(c *C) {
   201  	defCaus := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeString), Index: 0}
   202  	baseFunc, err := newBaseBuiltinFunc(mock.NewContext(), "", []Expression{defCaus}, 0)
   203  	if err != nil {
   204  		panic(err)
   205  	}
   206  	// set `inUnion` to `true`
   207  	baseCast := newBaseBuiltinCastFunc(baseFunc, true)
   208  	baseCast.tp = types.NewFieldType(allegrosql.TypeNewDecimal)
   209  	// set the `UnsignedFlag` bit
   210  	baseCast.tp.Flag |= allegrosql.UnsignedFlag
   211  	cast := &builtinCastStringAsDecimalSig{baseCast}
   212  
   213  	inputs := []*chunk.Chunk{
   214  		genCastStringAsDecimal(false),
   215  		genCastStringAsDecimal(true),
   216  	}
   217  
   218  	for _, input := range inputs {
   219  		result := chunk.NewDeferredCauset(types.NewFieldType(allegrosql.TypeNewDecimal), input.NumEvents())
   220  		c.Assert(cast.vecEvalDecimal(input, result), IsNil)
   221  		for i := 0; i < input.NumEvents(); i++ {
   222  			res, isNull, err := cast.evalDecimal(input.GetEvent(i))
   223  			c.Assert(isNull, IsFalse)
   224  			c.Assert(err, IsNil)
   225  			c.Assert(result.GetDecimal(i).Compare(res), Equals, 0)
   226  		}
   227  	}
   228  }
   229  
   230  func genCastStringAsDecimal(isNegative bool) *chunk.Chunk {
   231  	var sign float64
   232  	if isNegative {
   233  		sign = -1
   234  	} else {
   235  		sign = 1
   236  	}
   237  
   238  	input := chunk.NewChunkWithCapacity([]*types.FieldType{types.NewFieldType(allegrosql.TypeString)}, 1024)
   239  	for i := 0; i < 1024; i++ {
   240  		d := new(types.MyDecimal)
   241  		f := sign * rand.Float64() * 100000
   242  		if err := d.FromFloat64(f); err != nil {
   243  			panic(err)
   244  		}
   245  		input.AppendString(0, d.String())
   246  	}
   247  
   248  	return input
   249  }
   250  
   251  func BenchmarkVectorizedBuiltinCastEvalOneVec(b *testing.B) {
   252  	benchmarkVectorizedEvalOneVec(b, vecBuiltinCastCases)
   253  }
   254  
   255  func BenchmarkVectorizedBuiltinCastFunc(b *testing.B) {
   256  	benchmarkVectorizedBuiltinFunc(b, vecBuiltinCastCases)
   257  }