storj.io/minio@v0.0.0-20230509071714-0cbc90f649b1/pkg/s3select/sql/evaluate.go (about)

     1  /*
     2   * MinIO Cloud Storage, (C) 2019 MinIO, Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package sql
    18  
    19  import (
    20  	"encoding/json"
    21  	"errors"
    22  	"fmt"
    23  	"math"
    24  
    25  	"github.com/bcicen/jstream"
    26  	"github.com/minio/simdjson-go"
    27  )
    28  
    29  var (
    30  	errInvalidASTNode    = errors.New("invalid AST Node")
    31  	errExpectedBool      = errors.New("expected bool")
    32  	errLikeNonStrArg     = errors.New("LIKE clause requires string arguments")
    33  	errLikeInvalidEscape = errors.New("LIKE clause has invalid ESCAPE character")
    34  	errNotImplemented    = errors.New("not implemented")
    35  )
    36  
    37  // AST Node Evaluation functions
    38  //
    39  // During evaluation, the query is known to be valid, as analysis is
    40  // complete. The only errors possible are due to value type
    41  // mismatches, etc.
    42  //
    43  // If an aggregation node is present as a descendant (when
    44  // e.prop.isAggregation is true), we call evalNode on all child nodes,
    45  // check for errors, but do not perform any combining of the results
    46  // of child nodes. The final result row is returned after all rows are
    47  // processed, and the `getAggregate` function is called.
    48  
    49  func (e *AliasedExpression) evalNode(r Record, tableAlias string) (*Value, error) {
    50  	return e.Expression.evalNode(r, tableAlias)
    51  }
    52  
    53  func (e *Expression) evalNode(r Record, tableAlias string) (*Value, error) {
    54  	if len(e.And) == 1 {
    55  		// In this case, result is not required to be boolean
    56  		// type.
    57  		return e.And[0].evalNode(r, tableAlias)
    58  	}
    59  
    60  	// Compute OR of conditions
    61  	result := false
    62  	for _, ex := range e.And {
    63  		res, err := ex.evalNode(r, tableAlias)
    64  		if err != nil {
    65  			return nil, err
    66  		}
    67  		b, ok := res.ToBool()
    68  		if !ok {
    69  			return nil, errExpectedBool
    70  		}
    71  		result = result || b
    72  	}
    73  	return FromBool(result), nil
    74  }
    75  
    76  func (e *AndCondition) evalNode(r Record, tableAlias string) (*Value, error) {
    77  	if len(e.Condition) == 1 {
    78  		// In this case, result does not have to be boolean
    79  		return e.Condition[0].evalNode(r, tableAlias)
    80  	}
    81  
    82  	// Compute AND of conditions
    83  	result := true
    84  	for _, ex := range e.Condition {
    85  		res, err := ex.evalNode(r, tableAlias)
    86  		if err != nil {
    87  			return nil, err
    88  		}
    89  		b, ok := res.ToBool()
    90  		if !ok {
    91  			return nil, errExpectedBool
    92  		}
    93  		result = result && b
    94  	}
    95  	return FromBool(result), nil
    96  }
    97  
    98  func (e *Condition) evalNode(r Record, tableAlias string) (*Value, error) {
    99  	if e.Operand != nil {
   100  		// In this case, result does not have to be boolean
   101  		return e.Operand.evalNode(r, tableAlias)
   102  	}
   103  
   104  	// Compute NOT of condition
   105  	res, err := e.Not.evalNode(r, tableAlias)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	b, ok := res.ToBool()
   110  	if !ok {
   111  		return nil, errExpectedBool
   112  	}
   113  	return FromBool(!b), nil
   114  }
   115  
   116  func (e *ConditionOperand) evalNode(r Record, tableAlias string) (*Value, error) {
   117  	opVal, opErr := e.Operand.evalNode(r, tableAlias)
   118  	if opErr != nil || e.ConditionRHS == nil {
   119  		return opVal, opErr
   120  	}
   121  
   122  	// Need to evaluate the ConditionRHS
   123  	switch {
   124  	case e.ConditionRHS.Compare != nil:
   125  		cmpRight, cmpRErr := e.ConditionRHS.Compare.Operand.evalNode(r, tableAlias)
   126  		if cmpRErr != nil {
   127  			return nil, cmpRErr
   128  		}
   129  
   130  		b, err := opVal.compareOp(e.ConditionRHS.Compare.Operator, cmpRight)
   131  		return FromBool(b), err
   132  
   133  	case e.ConditionRHS.Between != nil:
   134  		return e.ConditionRHS.Between.evalBetweenNode(r, opVal, tableAlias)
   135  
   136  	case e.ConditionRHS.Like != nil:
   137  		return e.ConditionRHS.Like.evalLikeNode(r, opVal, tableAlias)
   138  
   139  	case e.ConditionRHS.In != nil:
   140  		return e.ConditionRHS.In.evalInNode(r, opVal, tableAlias)
   141  
   142  	default:
   143  		return nil, errInvalidASTNode
   144  	}
   145  }
   146  
   147  func (e *Between) evalBetweenNode(r Record, arg *Value, tableAlias string) (*Value, error) {
   148  	stVal, stErr := e.Start.evalNode(r, tableAlias)
   149  	if stErr != nil {
   150  		return nil, stErr
   151  	}
   152  
   153  	endVal, endErr := e.End.evalNode(r, tableAlias)
   154  	if endErr != nil {
   155  		return nil, endErr
   156  	}
   157  
   158  	part1, err1 := stVal.compareOp(opLte, arg)
   159  	if err1 != nil {
   160  		return nil, err1
   161  	}
   162  
   163  	part2, err2 := arg.compareOp(opLte, endVal)
   164  	if err2 != nil {
   165  		return nil, err2
   166  	}
   167  
   168  	result := part1 && part2
   169  	if e.Not {
   170  		result = !result
   171  	}
   172  
   173  	return FromBool(result), nil
   174  }
   175  
   176  func (e *Like) evalLikeNode(r Record, arg *Value, tableAlias string) (*Value, error) {
   177  	inferTypeAsString(arg)
   178  
   179  	s, ok := arg.ToString()
   180  	if !ok {
   181  		err := errLikeNonStrArg
   182  		return nil, errLikeInvalidInputs(err)
   183  	}
   184  
   185  	pattern, err1 := e.Pattern.evalNode(r, tableAlias)
   186  	if err1 != nil {
   187  		return nil, err1
   188  	}
   189  
   190  	// Infer pattern as string (in case it is untyped)
   191  	inferTypeAsString(pattern)
   192  
   193  	patternStr, ok := pattern.ToString()
   194  	if !ok {
   195  		err := errLikeNonStrArg
   196  		return nil, errLikeInvalidInputs(err)
   197  	}
   198  
   199  	escape := runeZero
   200  	if e.EscapeChar != nil {
   201  		escapeVal, err2 := e.EscapeChar.evalNode(r, tableAlias)
   202  		if err2 != nil {
   203  			return nil, err2
   204  		}
   205  
   206  		inferTypeAsString(escapeVal)
   207  
   208  		escapeStr, ok := escapeVal.ToString()
   209  		if !ok {
   210  			err := errLikeNonStrArg
   211  			return nil, errLikeInvalidInputs(err)
   212  		}
   213  
   214  		if len([]rune(escapeStr)) > 1 {
   215  			err := errLikeInvalidEscape
   216  			return nil, errLikeInvalidInputs(err)
   217  		}
   218  	}
   219  
   220  	matchResult, err := evalSQLLike(s, patternStr, escape)
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  
   225  	if e.Not {
   226  		matchResult = !matchResult
   227  	}
   228  
   229  	return FromBool(matchResult), nil
   230  }
   231  
   232  func (e *ListExpr) evalNode(r Record, tableAlias string) (*Value, error) {
   233  	res := make([]Value, len(e.Elements))
   234  	if len(e.Elements) == 1 {
   235  		// If length 1, treat as single value.
   236  		return e.Elements[0].evalNode(r, tableAlias)
   237  	}
   238  	for i, elt := range e.Elements {
   239  		v, err := elt.evalNode(r, tableAlias)
   240  		if err != nil {
   241  			return nil, err
   242  		}
   243  		res[i] = *v
   244  	}
   245  	return FromArray(res), nil
   246  }
   247  
   248  const floatCmpTolerance = 0.000001
   249  
   250  func (e *In) evalInNode(r Record, lhs *Value, tableAlias string) (*Value, error) {
   251  	// Compare two values in terms of in-ness.
   252  	var cmp func(a, b Value) bool
   253  	cmp = func(a, b Value) bool {
   254  		// Convert if needed.
   255  		inferTypesForCmp(&a, &b)
   256  
   257  		if a.Equals(b) {
   258  			return true
   259  		}
   260  
   261  		// If elements, compare each.
   262  		aA, aOK := a.ToArray()
   263  		bA, bOK := b.ToArray()
   264  		if aOK && bOK {
   265  			if len(aA) != len(bA) {
   266  				return false
   267  			}
   268  			for i := range aA {
   269  				if !cmp(aA[i], bA[i]) {
   270  					return false
   271  				}
   272  			}
   273  			return true
   274  		}
   275  		// Try as numbers
   276  		aF, aOK := a.ToFloat()
   277  		bF, bOK := b.ToFloat()
   278  
   279  		diff := math.Abs(aF - bF)
   280  		return aOK && bOK && diff < floatCmpTolerance
   281  	}
   282  
   283  	var rhs Value
   284  	if elt := e.ListExpression; elt != nil {
   285  		eltVal, err := elt.evalNode(r, tableAlias)
   286  		if err != nil {
   287  			return nil, err
   288  		}
   289  		rhs = *eltVal
   290  	}
   291  
   292  	// If RHS is array compare each element.
   293  	if arr, ok := rhs.ToArray(); ok {
   294  		for _, element := range arr {
   295  			// If we have an array we are on the wrong level.
   296  			if cmp(element, *lhs) {
   297  				return FromBool(true), nil
   298  			}
   299  		}
   300  		return FromBool(false), nil
   301  	}
   302  
   303  	return FromBool(cmp(rhs, *lhs)), nil
   304  }
   305  
   306  func (e *Operand) evalNode(r Record, tableAlias string) (*Value, error) {
   307  	lval, lerr := e.Left.evalNode(r, tableAlias)
   308  	if lerr != nil || len(e.Right) == 0 {
   309  		return lval, lerr
   310  	}
   311  
   312  	// Process remaining child nodes - result must be
   313  	// numeric. This AST node is for terms separated by + or -
   314  	// symbols.
   315  	for _, rightTerm := range e.Right {
   316  		op := rightTerm.Op
   317  		rval, rerr := rightTerm.Right.evalNode(r, tableAlias)
   318  		if rerr != nil {
   319  			return nil, rerr
   320  		}
   321  		err := lval.arithOp(op, rval)
   322  		if err != nil {
   323  			return nil, err
   324  		}
   325  	}
   326  	return lval, nil
   327  }
   328  
   329  func (e *MultOp) evalNode(r Record, tableAlias string) (*Value, error) {
   330  	lval, lerr := e.Left.evalNode(r, tableAlias)
   331  	if lerr != nil || len(e.Right) == 0 {
   332  		return lval, lerr
   333  	}
   334  
   335  	// Process other child nodes - result must be numeric. This
   336  	// AST node is for terms separated by *, / or % symbols.
   337  	for _, rightTerm := range e.Right {
   338  		op := rightTerm.Op
   339  		rval, rerr := rightTerm.Right.evalNode(r, tableAlias)
   340  		if rerr != nil {
   341  			return nil, rerr
   342  		}
   343  
   344  		err := lval.arithOp(op, rval)
   345  		if err != nil {
   346  			return nil, err
   347  		}
   348  	}
   349  	return lval, nil
   350  }
   351  
   352  func (e *UnaryTerm) evalNode(r Record, tableAlias string) (*Value, error) {
   353  	if e.Negated == nil {
   354  		return e.Primary.evalNode(r, tableAlias)
   355  	}
   356  
   357  	v, err := e.Negated.Term.evalNode(r, tableAlias)
   358  	if err != nil {
   359  		return nil, err
   360  	}
   361  
   362  	inferTypeForArithOp(v)
   363  	v.negate()
   364  	if v.isNumeric() {
   365  		return v, nil
   366  	}
   367  	return nil, errArithMismatchedTypes
   368  }
   369  
   370  func (e *JSONPath) evalNode(r Record, tableAlias string) (*Value, error) {
   371  	alias := tableAlias
   372  	if tableAlias == "" {
   373  		alias = baseTableName
   374  	}
   375  	pathExpr := e.StripTableAlias(alias)
   376  	_, rawVal := r.Raw()
   377  	switch rowVal := rawVal.(type) {
   378  	case jstream.KVS, simdjson.Object:
   379  		if len(pathExpr) == 0 {
   380  			pathExpr = []*JSONPathElement{{Key: &ObjectKey{ID: e.BaseKey}}}
   381  		}
   382  
   383  		result, _, err := jsonpathEval(pathExpr, rowVal)
   384  		if err != nil {
   385  			return nil, err
   386  		}
   387  
   388  		return jsonToValue(result)
   389  	default:
   390  		if pathExpr[len(pathExpr)-1].Key == nil {
   391  			return nil, errInvalidKeypath
   392  		}
   393  		return r.Get(pathExpr[len(pathExpr)-1].Key.keyString())
   394  	}
   395  }
   396  
   397  // jsonToValue will convert the json value to an internal value.
   398  func jsonToValue(result interface{}) (*Value, error) {
   399  	switch rval := result.(type) {
   400  	case string:
   401  		return FromString(rval), nil
   402  	case float64:
   403  		return FromFloat(rval), nil
   404  	case int64:
   405  		return FromInt(rval), nil
   406  	case uint64:
   407  		if rval <= math.MaxInt64 {
   408  			return FromInt(int64(rval)), nil
   409  		}
   410  		return FromFloat(float64(rval)), nil
   411  	case bool:
   412  		return FromBool(rval), nil
   413  	case jstream.KVS:
   414  		bs, err := json.Marshal(result)
   415  		if err != nil {
   416  			return nil, err
   417  		}
   418  		return FromBytes(bs), nil
   419  	case []interface{}:
   420  		dst := make([]Value, len(rval))
   421  		for i := range rval {
   422  			v, err := jsonToValue(rval[i])
   423  			if err != nil {
   424  				return nil, err
   425  			}
   426  			dst[i] = *v
   427  		}
   428  		return FromArray(dst), nil
   429  	case simdjson.Object:
   430  		o := rval
   431  		elems, err := o.Parse(nil)
   432  		if err != nil {
   433  			return nil, err
   434  		}
   435  		bs, err := elems.MarshalJSON()
   436  		if err != nil {
   437  			return nil, err
   438  		}
   439  		return FromBytes(bs), nil
   440  	case []Value:
   441  		return FromArray(rval), nil
   442  	case nil:
   443  		return FromNull(), nil
   444  	}
   445  	return nil, fmt.Errorf("Unhandled value type: %T", result)
   446  }
   447  
   448  func (e *PrimaryTerm) evalNode(r Record, tableAlias string) (res *Value, err error) {
   449  	switch {
   450  	case e.Value != nil:
   451  		return e.Value.evalNode(r)
   452  	case e.JPathExpr != nil:
   453  		return e.JPathExpr.evalNode(r, tableAlias)
   454  	case e.ListExpr != nil:
   455  		return e.ListExpr.evalNode(r, tableAlias)
   456  	case e.SubExpression != nil:
   457  		return e.SubExpression.evalNode(r, tableAlias)
   458  	case e.FuncCall != nil:
   459  		return e.FuncCall.evalNode(r, tableAlias)
   460  	}
   461  	return nil, errInvalidASTNode
   462  }
   463  
   464  func (e *FuncExpr) evalNode(r Record, tableAlias string) (res *Value, err error) {
   465  	switch e.getFunctionName() {
   466  	case aggFnCount, aggFnAvg, aggFnMax, aggFnMin, aggFnSum:
   467  		return e.getAggregate()
   468  	default:
   469  		return e.evalSQLFnNode(r, tableAlias)
   470  	}
   471  }
   472  
   473  // evalNode on a literal value is independent of the node being an
   474  // aggregation or a row function - it always returns a value.
   475  func (e *LitValue) evalNode(_ Record) (res *Value, err error) {
   476  	switch {
   477  	case e.Int != nil:
   478  		if *e.Int < math.MaxInt64 && *e.Int > math.MinInt64 {
   479  			return FromInt(int64(*e.Int)), nil
   480  		}
   481  		return FromFloat(*e.Int), nil
   482  	case e.Float != nil:
   483  		return FromFloat(*e.Float), nil
   484  	case e.String != nil:
   485  		return FromString(string(*e.String)), nil
   486  	case e.Boolean != nil:
   487  		return FromBool(bool(*e.Boolean)), nil
   488  	}
   489  	return FromNull(), nil
   490  }