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 }