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 }