github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/memristed/memex/builtin_compare_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 "time" 18 19 . "github.com/whtcorpsinc/check" 20 "github.com/whtcorpsinc/errors" 21 "github.com/whtcorpsinc/BerolinaSQL/ast" 22 "github.com/whtcorpsinc/BerolinaSQL/perceptron" 23 "github.com/whtcorpsinc/BerolinaSQL/allegrosql" 24 "github.com/whtcorpsinc/milevadb/types" 25 "github.com/whtcorpsinc/milevadb/types/json" 26 "github.com/whtcorpsinc/milevadb/soliton/chunk" 27 ) 28 29 func (s *testEvaluatorSuite) TestCompareFunctionWithRefine(c *C) { 30 tblInfo := newTestBlockBuilder("").add("a", allegrosql.TypeLong).build() 31 tests := []struct { 32 exprStr string 33 result string 34 }{ 35 {"a < '1.0'", "lt(a, 1)"}, 36 {"a <= '1.0'", "le(a, 1)"}, 37 {"a > '1'", "gt(a, 1)"}, 38 {"a >= '1'", "ge(a, 1)"}, 39 {"a = '1'", "eq(a, 1)"}, 40 {"a <=> '1'", "nulleq(a, 1)"}, 41 {"a != '1'", "ne(a, 1)"}, 42 {"a < '1.1'", "lt(a, 2)"}, 43 {"a <= '1.1'", "le(a, 1)"}, 44 {"a > 1.1", "gt(a, 1)"}, 45 {"a >= '1.1'", "ge(a, 2)"}, 46 {"a = '1.1'", "0"}, 47 {"a <=> '1.1'", "0"}, 48 {"a != '1.1'", "ne(cast(a, double BINARY), 1.1)"}, 49 {"'1' < a", "lt(1, a)"}, 50 {"'1' <= a", "le(1, a)"}, 51 {"'1' > a", "gt(1, a)"}, 52 {"'1' >= a", "ge(1, a)"}, 53 {"'1' = a", "eq(1, a)"}, 54 {"'1' <=> a", "nulleq(1, a)"}, 55 {"'1' != a", "ne(1, a)"}, 56 {"'1.1' < a", "lt(1, a)"}, 57 {"'1.1' <= a", "le(2, a)"}, 58 {"'1.1' > a", "gt(2, a)"}, 59 {"'1.1' >= a", "ge(1, a)"}, 60 {"'1.1' = a", "0"}, 61 {"'1.1' <=> a", "0"}, 62 {"'1.1' != a", "ne(1.1, cast(a, double BINARY))"}, 63 {"'123456789123456711111189' = a", "0"}, 64 {"123456789123456789.12345 = a", "0"}, 65 {"123456789123456789123456789.12345 > a", "1"}, 66 {"-123456789123456789123456789.12345 > a", "0"}, 67 {"123456789123456789123456789.12345 < a", "0"}, 68 {"-123456789123456789123456789.12345 < a", "1"}, 69 {"'aaaa'=a", "eq(0, a)"}, 70 } 71 defcaus, names, err := DeferredCausetInfos2DeferredCausetsAndNames(s.ctx, perceptron.NewCIStr(""), tblInfo.Name, tblInfo.DefCauss(), tblInfo) 72 c.Assert(err, IsNil) 73 schemaReplicant := NewSchema(defcaus...) 74 for _, t := range tests { 75 f, err := ParseSimpleExprsWithNames(s.ctx, t.exprStr, schemaReplicant, names) 76 c.Assert(err, IsNil) 77 c.Assert(f[0].String(), Equals, t.result) 78 } 79 } 80 81 func (s *testEvaluatorSuite) TestCompare(c *C) { 82 intVal, uintVal, realVal, stringVal, decimalVal := 1, uint64(1), 1.1, "123", types.NewDecFromFloatForTest(123.123) 83 timeVal := types.NewTime(types.FromGoTime(time.Now()), allegrosql.TypeDatetime, 6) 84 durationVal := types.Duration{Duration: 12*time.Hour + 1*time.Minute + 1*time.Second} 85 jsonVal := json.CreateBinary("123") 86 // test cases for generating function signatures. 87 tests := []struct { 88 arg0 interface{} 89 arg1 interface{} 90 funcName string 91 tp byte 92 expected int64 93 }{ 94 {intVal, intVal, ast.LT, allegrosql.TypeLonglong, 0}, 95 {stringVal, stringVal, ast.LT, allegrosql.TypeVarString, 0}, 96 {intVal, decimalVal, ast.LT, allegrosql.TypeNewDecimal, 1}, 97 {realVal, decimalVal, ast.LT, allegrosql.TypeDouble, 1}, 98 {durationVal, durationVal, ast.LT, allegrosql.TypeDuration, 0}, 99 {realVal, realVal, ast.LT, allegrosql.TypeDouble, 0}, 100 {intVal, intVal, ast.NullEQ, allegrosql.TypeLonglong, 1}, 101 {decimalVal, decimalVal, ast.LE, allegrosql.TypeNewDecimal, 1}, 102 {decimalVal, decimalVal, ast.GT, allegrosql.TypeNewDecimal, 0}, 103 {decimalVal, decimalVal, ast.GE, allegrosql.TypeNewDecimal, 1}, 104 {decimalVal, decimalVal, ast.NE, allegrosql.TypeNewDecimal, 0}, 105 {decimalVal, decimalVal, ast.EQ, allegrosql.TypeNewDecimal, 1}, 106 {decimalVal, decimalVal, ast.NullEQ, allegrosql.TypeNewDecimal, 1}, 107 {durationVal, durationVal, ast.LE, allegrosql.TypeDuration, 1}, 108 {durationVal, durationVal, ast.GT, allegrosql.TypeDuration, 0}, 109 {durationVal, durationVal, ast.GE, allegrosql.TypeDuration, 1}, 110 {durationVal, durationVal, ast.EQ, allegrosql.TypeDuration, 1}, 111 {durationVal, durationVal, ast.NE, allegrosql.TypeDuration, 0}, 112 {durationVal, durationVal, ast.NullEQ, allegrosql.TypeDuration, 1}, 113 {nil, nil, ast.NullEQ, allegrosql.TypeNull, 1}, 114 {nil, intVal, ast.NullEQ, allegrosql.TypeDouble, 0}, 115 {uintVal, intVal, ast.NullEQ, allegrosql.TypeLonglong, 1}, 116 {uintVal, intVal, ast.EQ, allegrosql.TypeLonglong, 1}, 117 {intVal, uintVal, ast.NullEQ, allegrosql.TypeLonglong, 1}, 118 {intVal, uintVal, ast.EQ, allegrosql.TypeLonglong, 1}, 119 {timeVal, timeVal, ast.LT, allegrosql.TypeDatetime, 0}, 120 {timeVal, timeVal, ast.LE, allegrosql.TypeDatetime, 1}, 121 {timeVal, timeVal, ast.GT, allegrosql.TypeDatetime, 0}, 122 {timeVal, timeVal, ast.GE, allegrosql.TypeDatetime, 1}, 123 {timeVal, timeVal, ast.EQ, allegrosql.TypeDatetime, 1}, 124 {timeVal, timeVal, ast.NE, allegrosql.TypeDatetime, 0}, 125 {timeVal, timeVal, ast.NullEQ, allegrosql.TypeDatetime, 1}, 126 {jsonVal, jsonVal, ast.LT, allegrosql.TypeJSON, 0}, 127 {jsonVal, jsonVal, ast.LE, allegrosql.TypeJSON, 1}, 128 {jsonVal, jsonVal, ast.GT, allegrosql.TypeJSON, 0}, 129 {jsonVal, jsonVal, ast.GE, allegrosql.TypeJSON, 1}, 130 {jsonVal, jsonVal, ast.NE, allegrosql.TypeJSON, 0}, 131 {jsonVal, jsonVal, ast.EQ, allegrosql.TypeJSON, 1}, 132 {jsonVal, jsonVal, ast.NullEQ, allegrosql.TypeJSON, 1}, 133 } 134 135 for _, t := range tests { 136 bf, err := funcs[t.funcName].getFunction(s.ctx, s.primitiveValsToConstants([]interface{}{t.arg0, t.arg1})) 137 c.Assert(err, IsNil) 138 args := bf.getArgs() 139 c.Assert(args[0].GetType().Tp, Equals, t.tp) 140 c.Assert(args[1].GetType().Tp, Equals, t.tp) 141 res, isNil, err := bf.evalInt(chunk.Event{}) 142 c.Assert(err, IsNil) 143 c.Assert(isNil, IsFalse) 144 c.Assert(res, Equals, t.expected) 145 } 146 147 // test <non-const decimal memex> <cmp> <const string memex> 148 decimalDefCaus, stringCon := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeNewDecimal)}, &Constant{RetType: types.NewFieldType(allegrosql.TypeVarchar)} 149 bf, err := funcs[ast.LT].getFunction(s.ctx, []Expression{decimalDefCaus, stringCon}) 150 c.Assert(err, IsNil) 151 args := bf.getArgs() 152 c.Assert(args[0].GetType().Tp, Equals, allegrosql.TypeNewDecimal) 153 c.Assert(args[1].GetType().Tp, Equals, allegrosql.TypeNewDecimal) 154 155 // test <time defCausumn> <cmp> <non-time const> 156 timeDefCaus := &DeferredCauset{RetType: types.NewFieldType(allegrosql.TypeDatetime)} 157 bf, err = funcs[ast.LT].getFunction(s.ctx, []Expression{timeDefCaus, stringCon}) 158 c.Assert(err, IsNil) 159 args = bf.getArgs() 160 c.Assert(args[0].GetType().Tp, Equals, allegrosql.TypeDatetime) 161 c.Assert(args[1].GetType().Tp, Equals, allegrosql.TypeDatetime) 162 } 163 164 func (s *testEvaluatorSuite) TestCoalesce(c *C) { 165 cases := []struct { 166 args []interface{} 167 expected interface{} 168 isNil bool 169 getErr bool 170 }{ 171 {[]interface{}{nil}, nil, true, false}, 172 {[]interface{}{nil, nil}, nil, true, false}, 173 {[]interface{}{nil, nil, nil}, nil, true, false}, 174 {[]interface{}{nil, 1}, int64(1), false, false}, 175 {[]interface{}{nil, 1.1}, float64(1.1), false, false}, 176 {[]interface{}{1, 1.1}, float64(1), false, false}, 177 {[]interface{}{nil, types.NewDecFromFloatForTest(123.456)}, types.NewDecFromFloatForTest(123.456), false, false}, 178 {[]interface{}{1, types.NewDecFromFloatForTest(123.456)}, types.NewDecFromInt(1), false, false}, 179 {[]interface{}{nil, duration}, duration, false, false}, 180 {[]interface{}{nil, tm, nil}, tm, false, false}, 181 {[]interface{}{nil, dt, nil}, dt, false, false}, 182 {[]interface{}{tm, dt}, tm, false, false}, 183 } 184 185 for _, t := range cases { 186 f, err := newFunctionForTest(s.ctx, ast.Coalesce, s.primitiveValsToConstants(t.args)...) 187 c.Assert(err, IsNil) 188 189 d, err := f.Eval(chunk.Event{}) 190 191 if t.getErr { 192 c.Assert(err, NotNil) 193 } else { 194 c.Assert(err, IsNil) 195 if t.isNil { 196 c.Assert(d.HoTT(), Equals, types.HoTTNull) 197 } else { 198 c.Assert(d.GetValue(), DeepEquals, t.expected) 199 } 200 } 201 } 202 203 _, err := funcs[ast.Length].getFunction(s.ctx, []Expression{NewZero()}) 204 c.Assert(err, IsNil) 205 } 206 207 func (s *testEvaluatorSuite) TestIntervalFunc(c *C) { 208 sc := s.ctx.GetStochastikVars().StmtCtx 209 origin := sc.IgnoreTruncate 210 sc.IgnoreTruncate = true 211 defer func() { 212 sc.IgnoreTruncate = origin 213 }() 214 215 for _, t := range []struct { 216 args []types.Causet 217 ret int64 218 getErr bool 219 }{ 220 {types.MakeCausets(nil, 1, 2), -1, false}, 221 {types.MakeCausets(1, 2, 3), 0, false}, 222 {types.MakeCausets(2, 1, 3), 1, false}, 223 {types.MakeCausets(3, 1, 2), 2, false}, 224 {types.MakeCausets(0, "b", "1", "2"), 1, false}, 225 {types.MakeCausets("a", "b", "1", "2"), 1, false}, 226 {types.MakeCausets(23, 1, 23, 23, 23, 30, 44, 200), 4, false}, 227 {types.MakeCausets(23, 1.7, 15.3, 23.1, 30, 44, 200), 2, false}, 228 {types.MakeCausets(9007199254740992, 9007199254740993), 0, false}, 229 {types.MakeCausets(uint64(9223372036854775808), uint64(9223372036854775809)), 0, false}, 230 {types.MakeCausets(9223372036854775807, uint64(9223372036854775808)), 0, false}, 231 {types.MakeCausets(-9223372036854775807, uint64(9223372036854775808)), 0, false}, 232 {types.MakeCausets(uint64(9223372036854775806), 9223372036854775807), 0, false}, 233 {types.MakeCausets(uint64(9223372036854775806), -9223372036854775807), 1, false}, 234 {types.MakeCausets("9007199254740991", "9007199254740992"), 0, false}, 235 {types.MakeCausets(1, uint32(1), uint32(1)), 0, true}, 236 {types.MakeCausets(-1, 2333, nil), 0, false}, 237 {types.MakeCausets(1, nil, nil, nil), 3, false}, 238 {types.MakeCausets(1, nil, nil, nil, 2), 3, false}, 239 {types.MakeCausets(uint64(9223372036854775808), nil, nil, nil, 4), 4, false}, 240 241 // tests for appropriate precision loss 242 {types.MakeCausets(9007199254740992, "9007199254740993"), 1, false}, 243 {types.MakeCausets("9007199254740992", 9007199254740993), 1, false}, 244 {types.MakeCausets("9007199254740992", "9007199254740993"), 1, false}, 245 } { 246 fc := funcs[ast.Interval] 247 f, err := fc.getFunction(s.ctx, s.datumsToConstants(t.args)) 248 c.Assert(err, IsNil) 249 if t.getErr { 250 v, err := evalBuiltinFunc(f, chunk.Event{}) 251 c.Assert(err, NotNil) 252 c.Assert(v.GetInt64(), Equals, t.ret) 253 continue 254 } 255 v, err := evalBuiltinFunc(f, chunk.Event{}) 256 c.Assert(err, IsNil) 257 c.Assert(v.GetInt64(), Equals, t.ret) 258 } 259 } 260 261 func (s *testEvaluatorSuite) TestGreatestLeastFuncs(c *C) { 262 sc := s.ctx.GetStochastikVars().StmtCtx 263 originIgnoreTruncate := sc.IgnoreTruncate 264 sc.IgnoreTruncate = true 265 defer func() { 266 sc.IgnoreTruncate = originIgnoreTruncate 267 }() 268 269 for _, t := range []struct { 270 args []interface{} 271 expectedGreatest interface{} 272 expectedLeast interface{} 273 isNil bool 274 getErr bool 275 }{ 276 { 277 []interface{}{1, 2, 3, 4}, 278 int64(4), int64(1), false, false, 279 }, 280 { 281 []interface{}{"a", "b", "c"}, 282 "c", "a", false, false, 283 }, 284 { 285 []interface{}{"123a", "b", "c", 12}, 286 float64(123), float64(0), false, false, 287 }, 288 { 289 []interface{}{tm, "123"}, 290 curTimeString, "123", false, false, 291 }, 292 { 293 []interface{}{tm, 123}, 294 curTimeInt, int64(123), false, false, 295 }, 296 { 297 []interface{}{tm, "invalid_time_1", "invalid_time_2", tmWithFsp}, 298 curTimeWithFspString, "invalid_time_1", false, false, 299 }, 300 { 301 []interface{}{tm, "invalid_time_2", "invalid_time_1", tmWithFsp}, 302 curTimeWithFspString, "invalid_time_2", false, false, 303 }, 304 { 305 []interface{}{tm, "invalid_time", nil, tmWithFsp}, 306 nil, nil, true, false, 307 }, 308 { 309 []interface{}{duration, "123"}, 310 "12:59:59", "123", false, false, 311 }, 312 { 313 []interface{}{"123", nil, "123"}, 314 nil, nil, true, false, 315 }, 316 { 317 []interface{}{errors.New("must error"), 123}, 318 nil, nil, false, true, 319 }, 320 } { 321 f0, err := newFunctionForTest(s.ctx, ast.Greatest, s.primitiveValsToConstants(t.args)...) 322 c.Assert(err, IsNil) 323 d, err := f0.Eval(chunk.Event{}) 324 if t.getErr { 325 c.Assert(err, NotNil) 326 } else { 327 c.Assert(err, IsNil) 328 if t.isNil { 329 c.Assert(d.HoTT(), Equals, types.HoTTNull) 330 } else { 331 c.Assert(d.GetValue(), DeepEquals, t.expectedGreatest) 332 } 333 } 334 335 f1, err := newFunctionForTest(s.ctx, ast.Least, s.primitiveValsToConstants(t.args)...) 336 c.Assert(err, IsNil) 337 d, err = f1.Eval(chunk.Event{}) 338 if t.getErr { 339 c.Assert(err, NotNil) 340 } else { 341 c.Assert(err, IsNil) 342 if t.isNil { 343 c.Assert(d.HoTT(), Equals, types.HoTTNull) 344 } else { 345 c.Assert(d.GetValue(), DeepEquals, t.expectedLeast) 346 } 347 } 348 } 349 _, err := funcs[ast.Greatest].getFunction(s.ctx, []Expression{NewZero(), NewOne()}) 350 c.Assert(err, IsNil) 351 _, err = funcs[ast.Least].getFunction(s.ctx, []Expression{NewZero(), NewOne()}) 352 c.Assert(err, IsNil) 353 }