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  }