github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/pingcap/tidb/xapi/xeval/eval.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 "sort" 18 "strings" 19 20 "github.com/insionng/yougam/libraries/juju/errors" 21 "github.com/insionng/yougam/libraries/pingcap/tidb/terror" 22 "github.com/insionng/yougam/libraries/pingcap/tidb/util/codec" 23 "github.com/insionng/yougam/libraries/pingcap/tidb/util/types" 24 "github.com/insionng/yougam/libraries/pingcap/tipb/go-tipb" 25 ) 26 27 // Error instances. 28 var ( 29 ErrInvalid = terror.ClassXEval.New(CodeInvalid, "invalid operation") 30 ) 31 32 // Error codes. 33 const ( 34 CodeInvalid = 1 35 ) 36 37 const ( 38 compareResultNull = -2 39 ) 40 41 // Evaluator evaluates tipb.Expr. 42 type Evaluator struct { 43 Row map[int64]types.Datum // column values. 44 valueLists map[*tipb.Expr]*decodedValueList 45 } 46 47 type decodedValueList struct { 48 values []types.Datum 49 hasNull bool 50 } 51 52 // Eval evaluates expr to a Datum. 53 func (e *Evaluator) Eval(expr *tipb.Expr) (types.Datum, error) { 54 switch expr.GetTp() { 55 case tipb.ExprType_Null: 56 return types.Datum{}, nil 57 case tipb.ExprType_Int64: 58 return e.evalInt(expr.Val) 59 case tipb.ExprType_Uint64: 60 return e.evalUint(expr.Val) 61 case tipb.ExprType_String: 62 return e.evalString(expr.Val) 63 case tipb.ExprType_Bytes: 64 return types.NewBytesDatum(expr.Val), nil 65 case tipb.ExprType_Float32: 66 return e.evalFloat(expr.Val, true) 67 case tipb.ExprType_Float64: 68 return e.evalFloat(expr.Val, false) 69 case tipb.ExprType_ColumnRef: 70 return e.evalColumnRef(expr.Val) 71 case tipb.ExprType_LT: 72 return e.evalLT(expr) 73 case tipb.ExprType_LE: 74 return e.evalLE(expr) 75 case tipb.ExprType_EQ: 76 return e.evalEQ(expr) 77 case tipb.ExprType_NE: 78 return e.evalNE(expr) 79 case tipb.ExprType_GE: 80 return e.evalGE(expr) 81 case tipb.ExprType_GT: 82 return e.evalGT(expr) 83 case tipb.ExprType_NullEQ: 84 return e.evalNullEQ(expr) 85 case tipb.ExprType_And: 86 return e.evalAnd(expr) 87 case tipb.ExprType_Or: 88 return e.evalOr(expr) 89 case tipb.ExprType_Like: 90 return e.evalLike(expr) 91 case tipb.ExprType_Not: 92 return e.evalNot(expr) 93 case tipb.ExprType_In: 94 return e.evalIn(expr) 95 } 96 return types.Datum{}, nil 97 } 98 99 func (e *Evaluator) evalColumnRef(val []byte) (types.Datum, error) { 100 var d types.Datum 101 _, i, err := codec.DecodeInt(val) 102 if err != nil { 103 return d, errors.Trace(err) 104 } 105 d, ok := e.Row[i] 106 if !ok { 107 return d, ErrInvalid.Gen("column % x not found", val) 108 } 109 return d, nil 110 } 111 112 func (e *Evaluator) evalInt(val []byte) (types.Datum, error) { 113 var d types.Datum 114 _, i, err := codec.DecodeInt(val) 115 if err != nil { 116 return d, ErrInvalid.Gen("invalid int % x", val) 117 } 118 d.SetInt64(i) 119 return d, nil 120 } 121 122 func (e *Evaluator) evalUint(val []byte) (types.Datum, error) { 123 var d types.Datum 124 _, u, err := codec.DecodeUint(val) 125 if err != nil { 126 return d, ErrInvalid.Gen("invalid uint % x", val) 127 } 128 d.SetUint64(u) 129 return d, nil 130 } 131 132 func (e *Evaluator) evalString(val []byte) (types.Datum, error) { 133 var d types.Datum 134 d.SetBytesAsString(val) 135 return d, nil 136 } 137 138 func (e *Evaluator) evalFloat(val []byte, f32 bool) (types.Datum, error) { 139 var d types.Datum 140 _, f, err := codec.DecodeFloat(val) 141 if err != nil { 142 return d, ErrInvalid.Gen("invalid float % x", val) 143 } 144 if f32 { 145 d.SetFloat32(float32(f)) 146 } else { 147 d.SetFloat64(f) 148 } 149 return d, nil 150 } 151 152 func (e *Evaluator) evalLT(expr *tipb.Expr) (types.Datum, error) { 153 cmp, err := e.compareTwoChildren(expr) 154 if err != nil { 155 return types.Datum{}, errors.Trace(err) 156 } 157 if cmp == compareResultNull { 158 return types.Datum{}, nil 159 } else if cmp < 0 { 160 return types.NewIntDatum(1), nil 161 } else { 162 return types.NewIntDatum(0), nil 163 } 164 } 165 166 func (e *Evaluator) evalLE(expr *tipb.Expr) (types.Datum, error) { 167 cmp, err := e.compareTwoChildren(expr) 168 if err != nil { 169 return types.Datum{}, errors.Trace(err) 170 } 171 if cmp == compareResultNull { 172 return types.Datum{}, nil 173 } else if cmp <= 0 { 174 return types.NewIntDatum(1), nil 175 } else { 176 return types.NewIntDatum(0), nil 177 } 178 } 179 180 func (e *Evaluator) evalEQ(expr *tipb.Expr) (types.Datum, error) { 181 cmp, err := e.compareTwoChildren(expr) 182 if err != nil { 183 return types.Datum{}, errors.Trace(err) 184 } 185 if cmp == compareResultNull { 186 return types.Datum{}, nil 187 } else if cmp == 0 { 188 return types.NewIntDatum(1), nil 189 } else { 190 return types.NewIntDatum(0), nil 191 } 192 } 193 194 func (e *Evaluator) evalNE(expr *tipb.Expr) (types.Datum, error) { 195 cmp, err := e.compareTwoChildren(expr) 196 if err != nil { 197 return types.Datum{}, errors.Trace(err) 198 } 199 if cmp == compareResultNull { 200 return types.Datum{}, nil 201 } else if cmp != 0 { 202 return types.NewIntDatum(1), nil 203 } else { 204 return types.NewIntDatum(0), nil 205 } 206 } 207 208 func (e *Evaluator) evalGE(expr *tipb.Expr) (types.Datum, error) { 209 cmp, err := e.compareTwoChildren(expr) 210 if err != nil { 211 return types.Datum{}, errors.Trace(err) 212 } 213 if cmp == compareResultNull { 214 return types.Datum{}, nil 215 } else if cmp >= 0 { 216 return types.NewIntDatum(1), nil 217 } else { 218 return types.NewIntDatum(0), nil 219 } 220 } 221 222 func (e *Evaluator) evalGT(expr *tipb.Expr) (types.Datum, error) { 223 cmp, err := e.compareTwoChildren(expr) 224 if err != nil { 225 return types.Datum{}, errors.Trace(err) 226 } 227 if cmp == compareResultNull { 228 return types.Datum{}, nil 229 } else if cmp > 0 { 230 return types.NewIntDatum(1), nil 231 } else { 232 return types.NewIntDatum(0), nil 233 } 234 } 235 236 func (e *Evaluator) evalNullEQ(expr *tipb.Expr) (types.Datum, error) { 237 left, right, err := e.evalTwoChildren(expr) 238 if err != nil { 239 return types.Datum{}, errors.Trace(err) 240 } 241 cmp, err := left.CompareDatum(right) 242 if err != nil { 243 return types.Datum{}, errors.Trace(err) 244 } 245 if cmp == 0 { 246 return types.NewIntDatum(1), nil 247 } 248 return types.NewIntDatum(0), nil 249 } 250 251 func (e *Evaluator) compareTwoChildren(expr *tipb.Expr) (int, error) { 252 left, right, err := e.evalTwoChildren(expr) 253 if err != nil { 254 return 0, errors.Trace(err) 255 } 256 if left.Kind() == types.KindNull || right.Kind() == types.KindNull { 257 return compareResultNull, nil 258 } 259 return left.CompareDatum(right) 260 } 261 262 func (e *Evaluator) evalAnd(expr *tipb.Expr) (types.Datum, error) { 263 leftBool, rightBool, err := e.evalTwoBoolChildren(expr) 264 if err != nil { 265 return types.Datum{}, errors.Trace(err) 266 } 267 var d types.Datum 268 if leftBool == 0 || rightBool == 0 { 269 d.SetInt64(0) 270 return d, nil 271 } 272 if leftBool == compareResultNull || rightBool == compareResultNull { 273 d.SetNull() 274 return d, nil 275 } 276 d.SetInt64(1) 277 return d, nil 278 } 279 280 func (e *Evaluator) evalOr(expr *tipb.Expr) (types.Datum, error) { 281 leftBool, rightBool, err := e.evalTwoBoolChildren(expr) 282 if err != nil { 283 return types.Datum{}, errors.Trace(err) 284 } 285 var d types.Datum 286 if leftBool == 1 || rightBool == 1 { 287 d.SetInt64(1) 288 return d, nil 289 } 290 if leftBool == compareResultNull || rightBool == compareResultNull { 291 d.SetNull() 292 return d, nil 293 } 294 d.SetInt64(0) 295 return d, nil 296 } 297 298 func (e *Evaluator) evalTwoBoolChildren(expr *tipb.Expr) (leftBool, rightBool int64, err error) { 299 left, right, err := e.evalTwoChildren(expr) 300 if err != nil { 301 return 0, 0, errors.Trace(err) 302 } 303 if left.Kind() == types.KindNull { 304 leftBool = compareResultNull 305 } else { 306 leftBool, err = left.ToBool() 307 if err != nil { 308 return 0, 0, errors.Trace(err) 309 } 310 } 311 if right.Kind() == types.KindNull { 312 rightBool = compareResultNull 313 } else { 314 rightBool, err = right.ToBool() 315 if err != nil { 316 return 0, 0, errors.Trace(err) 317 } 318 } 319 return 320 } 321 322 func (e *Evaluator) evalTwoChildren(expr *tipb.Expr) (left, right types.Datum, err error) { 323 if len(expr.Children) != 2 { 324 err = ErrInvalid.Gen("need 2 operands but got %d", len(expr.Children)) 325 return 326 } 327 left, err = e.Eval(expr.Children[0]) 328 if err != nil { 329 return types.Datum{}, types.Datum{}, errors.Trace(err) 330 } 331 right, err = e.Eval(expr.Children[1]) 332 if err != nil { 333 return types.Datum{}, types.Datum{}, errors.Trace(err) 334 } 335 return 336 } 337 338 func (e *Evaluator) evalLike(expr *tipb.Expr) (types.Datum, error) { 339 target, pattern, err := e.evalTwoChildren(expr) 340 if err != nil { 341 return types.Datum{}, errors.Trace(err) 342 } 343 if target.Kind() == types.KindNull || pattern.Kind() == types.KindNull { 344 return types.Datum{}, nil 345 } 346 targetStr, err := target.ToString() 347 if err != nil { 348 return types.Datum{}, errors.Trace(err) 349 } 350 patternStr, err := pattern.ToString() 351 if err != nil { 352 return types.Datum{}, errors.Trace(err) 353 } 354 if containsAlphabet(patternStr) { 355 patternStr = strings.ToLower(patternStr) 356 targetStr = strings.ToLower(targetStr) 357 } 358 mType, trimmedPattern := matchType(patternStr) 359 var matched bool 360 switch mType { 361 case matchExact: 362 matched = targetStr == trimmedPattern 363 case matchPrefix: 364 matched = strings.HasPrefix(targetStr, trimmedPattern) 365 case matchSuffix: 366 matched = strings.HasSuffix(targetStr, trimmedPattern) 367 case matchMiddle: 368 matched = strings.Index(targetStr, trimmedPattern) != -1 369 } 370 if matched { 371 return types.NewIntDatum(1), nil 372 } 373 return types.NewIntDatum(0), nil 374 } 375 376 func containsAlphabet(s string) bool { 377 for _, r := range s { 378 if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { 379 return true 380 } 381 } 382 return false 383 } 384 385 func matchType(pattern string) (tp int, trimmed string) { 386 switch len(pattern) { 387 case 0: 388 return matchExact, pattern 389 case 1: 390 if pattern[0] == '%' { 391 return matchMiddle, "" 392 } 393 return matchExact, pattern 394 default: 395 first := pattern[0] 396 last := pattern[len(pattern)-1] 397 if first == '%' { 398 if last == '%' { 399 return matchMiddle, pattern[1 : len(pattern)-1] 400 } 401 return matchSuffix, pattern[1:] 402 } 403 if last == '%' { 404 return matchPrefix, pattern[:len(pattern)-1] 405 } 406 return matchExact, pattern 407 } 408 } 409 410 const ( 411 matchExact = 1 412 matchPrefix = 2 413 matchSuffix = 3 414 matchMiddle = 4 415 ) 416 417 func (e *Evaluator) evalNot(expr *tipb.Expr) (types.Datum, error) { 418 if len(expr.Children) != 1 { 419 return types.Datum{}, ErrInvalid.Gen("NOT need 1 operand, got %d", len(expr.Children)) 420 } 421 d, err := e.Eval(expr.Children[0]) 422 if err != nil { 423 return types.Datum{}, errors.Trace(err) 424 } 425 if d.Kind() == types.KindNull { 426 return d, nil 427 } 428 boolVal, err := d.ToBool() 429 if err != nil { 430 return types.Datum{}, errors.Trace(err) 431 } 432 if boolVal == 1 { 433 return types.NewIntDatum(0), nil 434 } 435 return types.NewIntDatum(1), nil 436 } 437 438 func (e *Evaluator) evalIn(expr *tipb.Expr) (types.Datum, error) { 439 if len(expr.Children) != 2 { 440 return types.Datum{}, ErrInvalid.Gen("IN need 2 operand, got %d", len(expr.Children)) 441 } 442 target, err := e.Eval(expr.Children[0]) 443 if err != nil { 444 return types.Datum{}, errors.Trace(err) 445 } 446 if target.Kind() == types.KindNull { 447 return types.Datum{}, nil 448 } 449 valueListExpr := expr.Children[1] 450 if valueListExpr.GetTp() != tipb.ExprType_ValueList { 451 return types.Datum{}, ErrInvalid.Gen("the second children should be value list type") 452 } 453 decoded, err := e.decodeValueList(valueListExpr) 454 if err != nil { 455 return types.Datum{}, errors.Trace(err) 456 } 457 in, err := checkIn(target, decoded.values) 458 if err != nil { 459 return types.Datum{}, errors.Trace(err) 460 } 461 if in { 462 return types.NewDatum(1), nil 463 } 464 if decoded.hasNull { 465 return types.Datum{}, nil 466 } 467 return types.NewDatum(0), nil 468 } 469 470 // The value list is in sorted order so we can do a binary search. 471 func checkIn(target types.Datum, list []types.Datum) (bool, error) { 472 var outerErr error 473 n := sort.Search(len(list), func(i int) bool { 474 val := list[i] 475 cmp, err := val.CompareDatum(target) 476 if err != nil { 477 outerErr = errors.Trace(err) 478 return false 479 } 480 return cmp >= 0 481 }) 482 if outerErr != nil { 483 return false, errors.Trace(outerErr) 484 } 485 if n < 0 || n >= len(list) { 486 return false, nil 487 } 488 cmp, err := list[n].CompareDatum(target) 489 if err != nil { 490 return false, errors.Trace(err) 491 } 492 return cmp == 0, nil 493 } 494 495 func (e *Evaluator) decodeValueList(valueListExpr *tipb.Expr) (*decodedValueList, error) { 496 if len(valueListExpr.Val) == 0 { 497 // Empty value list. 498 return &decodedValueList{}, nil 499 } 500 if e.valueLists == nil { 501 e.valueLists = make(map[*tipb.Expr]*decodedValueList) 502 } 503 decoded := e.valueLists[valueListExpr] 504 if decoded != nil { 505 return decoded, nil 506 } 507 list, err := codec.Decode(valueListExpr.Val) 508 if err != nil { 509 return nil, errors.Trace(err) 510 } 511 var hasNull bool 512 for _, v := range list { 513 if v.Kind() == types.KindNull { 514 hasNull = true 515 } 516 } 517 decoded = &decodedValueList{values: list, hasNull: hasNull} 518 e.valueLists[valueListExpr] = decoded 519 return decoded, nil 520 }