github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/xapi/xeval/eval_test.go (about) 1 // Copyright 2016 PingCAP, 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 xeval 15 16 import ( 17 "testing" 18 19 . "github.com/insionng/yougam/libraries/pingcap/check" 20 "github.com/insionng/yougam/libraries/pingcap/tidb/util/codec" 21 "github.com/insionng/yougam/libraries/pingcap/tidb/util/types" 22 "github.com/insionng/yougam/libraries/pingcap/tipb/go-tipb" 23 ) 24 25 func TestT(t *testing.T) { 26 TestingT(t) 27 } 28 29 var _ = Suite(&testEvalSuite{}) 30 31 type testEvalSuite struct{} 32 33 // TODO: add more tests. 34 func (s *testEvalSuite) TestEval(c *C) { 35 colID := int64(1) 36 row := make(map[int64]types.Datum) 37 row[colID] = types.NewIntDatum(100) 38 xevaluator := &Evaluator{Row: row} 39 cases := []struct { 40 expr *tipb.Expr 41 result types.Datum 42 }{ 43 // Datums. 44 { 45 datumExpr(types.NewFloat32Datum(1.1)), 46 types.NewFloat32Datum(1.1), 47 }, 48 { 49 datumExpr(types.NewFloat64Datum(1.1)), 50 types.NewFloat64Datum(1.1), 51 }, 52 { 53 datumExpr(types.NewIntDatum(1)), 54 types.NewIntDatum(1), 55 }, 56 { 57 datumExpr(types.NewUintDatum(1)), 58 types.NewUintDatum(1), 59 }, 60 { 61 datumExpr(types.NewBytesDatum([]byte("abc"))), 62 types.NewBytesDatum([]byte("abc")), 63 }, 64 { 65 datumExpr(types.NewStringDatum("abc")), 66 types.NewStringDatum("abc"), 67 }, 68 { 69 datumExpr(types.Datum{}), 70 types.Datum{}, 71 }, 72 { 73 datumExpr(types.Datum{}), 74 types.Datum{}, 75 }, 76 { 77 columnExpr(1), 78 types.NewIntDatum(100), 79 }, 80 // Comparison operations. 81 { 82 binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_LT), 83 types.NewIntDatum(0), 84 }, 85 { 86 binaryExpr(types.NewIntDatum(1), types.NewIntDatum(100), tipb.ExprType_LT), 87 types.NewIntDatum(1), 88 }, 89 { 90 binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_LT), 91 types.Datum{}, 92 }, 93 { 94 binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_LE), 95 types.NewIntDatum(0), 96 }, 97 { 98 binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_LE), 99 types.NewIntDatum(1), 100 }, 101 { 102 binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_LE), 103 types.Datum{}, 104 }, 105 { 106 binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_EQ), 107 types.NewIntDatum(0), 108 }, 109 { 110 binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_EQ), 111 types.NewIntDatum(1), 112 }, 113 { 114 binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_EQ), 115 types.Datum{}, 116 }, 117 { 118 binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_NE), 119 types.NewIntDatum(0), 120 }, 121 { 122 binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_NE), 123 types.NewIntDatum(1), 124 }, 125 { 126 binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_NE), 127 types.Datum{}, 128 }, 129 { 130 binaryExpr(types.NewIntDatum(1), types.NewIntDatum(100), tipb.ExprType_GE), 131 types.NewIntDatum(0), 132 }, 133 { 134 binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_GE), 135 types.NewIntDatum(1), 136 }, 137 { 138 binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_GE), 139 types.Datum{}, 140 }, 141 { 142 binaryExpr(types.NewIntDatum(100), types.NewIntDatum(100), tipb.ExprType_GT), 143 types.NewIntDatum(0), 144 }, 145 { 146 binaryExpr(types.NewIntDatum(100), types.NewIntDatum(1), tipb.ExprType_GT), 147 types.NewIntDatum(1), 148 }, 149 { 150 binaryExpr(types.NewIntDatum(100), types.Datum{}, tipb.ExprType_GT), 151 types.Datum{}, 152 }, 153 { 154 binaryExpr(types.NewIntDatum(1), types.Datum{}, tipb.ExprType_NullEQ), 155 types.NewIntDatum(0), 156 }, 157 { 158 binaryExpr(types.Datum{}, types.Datum{}, tipb.ExprType_NullEQ), 159 types.NewIntDatum(1), 160 }, 161 // Logic operation. 162 { 163 binaryExpr(types.NewIntDatum(0), types.NewIntDatum(1), tipb.ExprType_And), 164 types.NewIntDatum(0), 165 }, 166 { 167 binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_And), 168 types.NewIntDatum(1), 169 }, 170 { 171 binaryExpr(types.NewIntDatum(0), types.Datum{}, tipb.ExprType_And), 172 types.NewIntDatum(0), 173 }, 174 { 175 binaryExpr(types.NewIntDatum(1), types.Datum{}, tipb.ExprType_And), 176 types.Datum{}, 177 }, 178 { 179 binaryExpr(types.NewIntDatum(0), types.NewIntDatum(0), tipb.ExprType_Or), 180 types.NewIntDatum(0), 181 }, 182 { 183 binaryExpr(types.NewIntDatum(0), types.NewIntDatum(1), tipb.ExprType_Or), 184 types.NewIntDatum(1), 185 }, 186 { 187 binaryExpr(types.NewIntDatum(0), types.Datum{}, tipb.ExprType_Or), 188 types.Datum{}, 189 }, 190 { 191 binaryExpr(types.NewIntDatum(1), types.Datum{}, tipb.ExprType_Or), 192 types.NewIntDatum(1), 193 }, 194 { 195 binaryExpr( 196 binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_EQ), 197 binaryExpr(types.NewIntDatum(1), types.NewIntDatum(1), tipb.ExprType_EQ), 198 tipb.ExprType_And), 199 types.NewIntDatum(1), 200 }, 201 { 202 notExpr(datumExpr(types.NewIntDatum(1))), 203 types.NewIntDatum(0), 204 }, 205 { 206 notExpr(datumExpr(types.NewIntDatum(0))), 207 types.NewIntDatum(1), 208 }, 209 { 210 notExpr(datumExpr(types.Datum{})), 211 types.Datum{}, 212 }, 213 } 214 for _, ca := range cases { 215 result, err := xevaluator.Eval(ca.expr) 216 c.Assert(err, IsNil) 217 c.Assert(result.Kind(), Equals, ca.result.Kind()) 218 cmp, err := result.CompareDatum(ca.result) 219 c.Assert(err, IsNil) 220 c.Assert(cmp, Equals, 0) 221 } 222 } 223 224 func binaryExpr(left, right interface{}, tp tipb.ExprType) *tipb.Expr { 225 expr := new(tipb.Expr) 226 expr.Tp = tp.Enum() 227 expr.Children = make([]*tipb.Expr, 2) 228 switch x := left.(type) { 229 case types.Datum: 230 expr.Children[0] = datumExpr(x) 231 case *tipb.Expr: 232 expr.Children[0] = x 233 } 234 switch x := right.(type) { 235 case types.Datum: 236 expr.Children[1] = datumExpr(x) 237 case *tipb.Expr: 238 expr.Children[1] = x 239 } 240 return expr 241 } 242 243 func datumExpr(d types.Datum) *tipb.Expr { 244 expr := new(tipb.Expr) 245 switch d.Kind() { 246 case types.KindInt64: 247 expr.Tp = tipb.ExprType_Int64.Enum() 248 expr.Val = codec.EncodeInt(nil, d.GetInt64()) 249 case types.KindUint64: 250 expr.Tp = tipb.ExprType_Uint64.Enum() 251 expr.Val = codec.EncodeUint(nil, d.GetUint64()) 252 case types.KindString: 253 expr.Tp = tipb.ExprType_String.Enum() 254 expr.Val = d.GetBytes() 255 case types.KindBytes: 256 expr.Tp = tipb.ExprType_Bytes.Enum() 257 expr.Val = d.GetBytes() 258 case types.KindFloat32: 259 expr.Tp = tipb.ExprType_Float32.Enum() 260 expr.Val = codec.EncodeFloat(nil, d.GetFloat64()) 261 case types.KindFloat64: 262 expr.Tp = tipb.ExprType_Float64.Enum() 263 expr.Val = codec.EncodeFloat(nil, d.GetFloat64()) 264 default: 265 expr.Tp = tipb.ExprType_Null.Enum() 266 } 267 return expr 268 } 269 270 func columnExpr(columnID int64) *tipb.Expr { 271 expr := new(tipb.Expr) 272 expr.Tp = tipb.ExprType_ColumnRef.Enum() 273 expr.Val = codec.EncodeInt(nil, columnID) 274 return expr 275 } 276 277 func likeExpr(target, pattern string) *tipb.Expr { 278 targetExpr := datumExpr(types.NewStringDatum(target)) 279 patternExpr := datumExpr(types.NewStringDatum(pattern)) 280 return &tipb.Expr{Tp: tipb.ExprType_Like.Enum(), Children: []*tipb.Expr{targetExpr, patternExpr}} 281 } 282 283 func notExpr(value interface{}) *tipb.Expr { 284 expr := new(tipb.Expr) 285 expr.Tp = tipb.ExprType_Not.Enum() 286 switch x := value.(type) { 287 case types.Datum: 288 expr.Children = []*tipb.Expr{datumExpr(x)} 289 case *tipb.Expr: 290 expr.Children = []*tipb.Expr{x} 291 } 292 return expr 293 } 294 295 func (s *testEvalSuite) TestLike(c *C) { 296 cases := []struct { 297 expr *tipb.Expr 298 result int64 299 }{ 300 { 301 expr: likeExpr("a", ""), 302 result: 0, 303 }, 304 { 305 expr: likeExpr("a", "a"), 306 result: 1, 307 }, 308 { 309 expr: likeExpr("a", "b"), 310 result: 0, 311 }, 312 { 313 expr: likeExpr("aAb", "AaB"), 314 result: 1, 315 }, 316 { 317 expr: likeExpr("a", "%"), 318 result: 1, 319 }, 320 { 321 expr: likeExpr("aAD", "%d"), 322 result: 1, 323 }, 324 { 325 expr: likeExpr("aAeD", "%e"), 326 result: 0, 327 }, 328 { 329 expr: likeExpr("aAb", "Aa%"), 330 result: 1, 331 }, 332 { 333 expr: likeExpr("abAb", "Aa%"), 334 result: 0, 335 }, 336 { 337 expr: likeExpr("aAcb", "%C%"), 338 result: 1, 339 }, 340 { 341 expr: likeExpr("aAb", "%C%"), 342 result: 0, 343 }, 344 } 345 ev := &Evaluator{} 346 for _, ca := range cases { 347 res, err := ev.Eval(ca.expr) 348 c.Check(err, IsNil) 349 c.Check(res.GetInt64(), Equals, ca.result) 350 } 351 } 352 353 func (s *testEvalSuite) TestWhereIn(c *C) { 354 cases := []struct { 355 expr *tipb.Expr 356 result interface{} 357 }{ 358 { 359 expr: inExpr(1, 1, 2), 360 result: true, 361 }, 362 { 363 expr: inExpr(1, 1, nil), 364 result: true, 365 }, 366 { 367 expr: inExpr(1, 2, nil), 368 result: nil, 369 }, 370 { 371 expr: inExpr(nil, 1, nil), 372 result: nil, 373 }, 374 { 375 expr: inExpr(2, 1, nil), 376 result: nil, 377 }, 378 { 379 expr: inExpr(2), 380 result: false, 381 }, 382 { 383 expr: inExpr("abc", "abc", "ab"), 384 result: true, 385 }, 386 { 387 expr: inExpr("abc", "aba", "bab"), 388 result: false, 389 }, 390 } 391 ev := &Evaluator{} 392 for _, ca := range cases { 393 res, err := ev.Eval(ca.expr) 394 c.Check(err, IsNil) 395 if ca.result == nil { 396 c.Check(res.Kind(), Equals, types.KindNull) 397 } else { 398 c.Check(res.Kind(), Equals, types.KindInt64) 399 if ca.result == true { 400 c.Check(res.GetInt64(), Equals, int64(1)) 401 } else { 402 c.Check(res.GetInt64(), Equals, int64(0)) 403 } 404 } 405 } 406 } 407 408 func inExpr(target interface{}, list ...interface{}) *tipb.Expr { 409 targetDatum := types.NewDatum(target) 410 var listDatums []types.Datum 411 for _, v := range list { 412 listDatums = append(listDatums, types.NewDatum(v)) 413 } 414 types.SortDatums(listDatums) 415 targetExpr := datumExpr(targetDatum) 416 val, _ := codec.EncodeValue(nil, listDatums...) 417 listExpr := &tipb.Expr{Tp: tipb.ExprType_ValueList.Enum(), Val: val} 418 return &tipb.Expr{Tp: tipb.ExprType_In.Enum(), Children: []*tipb.Expr{targetExpr, listExpr}} 419 }