go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/llx/builtin_map.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package llx 5 6 import ( 7 "errors" 8 "regexp" 9 "strconv" 10 "strings" 11 "sync" 12 13 "go.mondoo.com/cnquery/types" 14 ) 15 16 // mapFunctions are all the handlers for builtin array methods 17 var mapFunctions map[string]chunkHandlerV2 18 19 func mapGetIndexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 20 if bind.Value == nil { 21 return &RawData{Type: bind.Type.Child()}, 0, nil 22 } 23 24 args := chunk.Function.Args 25 26 // TODO: all this needs to go into the compile phase 27 if len(args) < 1 { 28 return nil, 0, errors.New("Called [] with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 29 } 30 if len(args) > 1 { 31 return nil, 0, errors.New("Called [] with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 32 } 33 t := types.Type(args[0].Type) 34 if t != types.String { 35 return nil, 0, errors.New("Called [] with wrong type " + t.Label()) 36 } 37 // ^^ TODO 38 39 key := string(args[0].Value) 40 childType := bind.Type.Child() 41 42 if bind.Value == nil { 43 return &RawData{ 44 Type: childType, 45 Value: nil, 46 }, 0, nil 47 } 48 49 m, ok := bind.Value.(map[string]interface{}) 50 if !ok { 51 return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into map") 52 } 53 return &RawData{ 54 Type: childType, 55 Value: m[key], 56 }, 0, nil 57 } 58 59 func mapCmpNil(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 60 if bind.Value == nil { 61 return BoolTrue, 0, nil 62 } 63 v, ok := bind.Value.(map[string]interface{}) 64 if !ok || v == nil { 65 return BoolTrue, 0, nil 66 } 67 return BoolFalse, 0, nil 68 } 69 70 func mapNotNil(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 71 if bind.Value == nil { 72 return BoolFalse, 0, nil 73 } 74 v, ok := bind.Value.(map[string]interface{}) 75 if !ok || v == nil { 76 return BoolFalse, 0, nil 77 } 78 return BoolTrue, 0, nil 79 } 80 81 func mapCmpEmpty(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 82 if bind.Value == nil { 83 return BoolTrue, 0, nil 84 } 85 v, ok := bind.Value.(map[string]interface{}) 86 if !ok || v == nil { 87 return BoolTrue, 0, nil 88 } 89 return BoolData(len(v) == 0), 0, nil 90 } 91 92 func mapNotEmpty(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 93 if bind.Value == nil { 94 return BoolFalse, 0, nil 95 } 96 v, ok := bind.Value.(map[string]interface{}) 97 if !ok || v == nil { 98 return BoolFalse, 0, nil 99 } 100 return BoolData(len(v) != 0), 0, nil 101 } 102 103 func mapLengthV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 104 if bind.Value == nil { 105 return &RawData{Type: types.Int}, 0, nil 106 } 107 108 arr, ok := bind.Value.(map[string]interface{}) 109 if !ok { 110 return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into map") 111 } 112 return IntData(int64(len(arr))), 0, nil 113 } 114 115 func _mapWhereV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64, invert bool) (*RawData, uint64, error) { 116 // where(array, function) 117 itemsRef := chunk.Function.Args[0] 118 items, rref, err := e.resolveValue(itemsRef, ref) 119 if err != nil || rref > 0 { 120 return nil, rref, err 121 } 122 123 if items.Value == nil { 124 return &RawData{Type: items.Type}, 0, nil 125 } 126 127 list := items.Value.(map[string]interface{}) 128 if len(list) == 0 { 129 return items, 0, nil 130 } 131 132 arg1 := chunk.Function.Args[1] 133 if types.Type(arg1.Type).Underlying() != types.FunctionLike { 134 return nil, 0, errors.New("cannot call 'where' on a map without a filter function") 135 } 136 137 fref, ok := arg1.RefV2() 138 if !ok { 139 return nil, 0, errors.New("failed to retrieve function reference of 'where' call") 140 } 141 142 dref, err := e.ensureArgsResolved(chunk.Function.Args[2:], ref) 143 if dref != 0 || err != nil { 144 return nil, dref, err 145 } 146 147 valueType := items.Type.Child() 148 149 argsList := make([][]*RawData, len(list)) 150 i := 0 151 for key, value := range list { 152 argsList[i] = []*RawData{ 153 { 154 Type: types.String, 155 Value: key, 156 }, 157 { 158 Type: valueType, 159 Value: value, 160 }, 161 } 162 i++ 163 } 164 165 err = e.runFunctionBlocks(argsList, fref, func(results []arrayBlockCallResult, errs []error) { 166 resMap := map[string]interface{}{} 167 for i, res := range results { 168 if res.isTruthy() == !invert { 169 key := argsList[i][0].Value.(string) 170 resMap[key] = list[key] 171 } 172 } 173 data := &RawData{ 174 Type: bind.Type, 175 Value: resMap, 176 } 177 e.cache.Store(ref, &stepCache{ 178 Result: data, 179 IsStatic: false, 180 }) 181 e.triggerChain(ref, data) 182 }) 183 184 if err != nil { 185 return nil, 0, err 186 } 187 188 return nil, 0, nil 189 } 190 191 func mapWhereV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 192 return _mapWhereV2(e, bind, chunk, ref, false) 193 } 194 195 func mapWhereNotV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 196 return _mapWhereV2(e, bind, chunk, ref, true) 197 } 198 199 func mapBlockCallV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 200 return e.runBlock(bind, chunk.Function.Args[0], nil, ref) 201 } 202 203 func mapKeysV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 204 if bind.Value == nil { 205 return &RawData{ 206 Type: types.Array(types.Dict), 207 Error: errors.New("Failed to get keys of `null`"), 208 }, 0, nil 209 } 210 211 m, ok := bind.Value.(map[string]interface{}) 212 if !ok { 213 return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into map") 214 } 215 216 res := make([]interface{}, len(m)) 217 var i int 218 for key := range m { 219 res[i] = key 220 i++ 221 } 222 223 return ArrayData(res, types.String), 0, nil 224 } 225 226 func mapValuesV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 227 typ := bind.Type.Child() 228 229 if bind.Value == nil { 230 return &RawData{ 231 Type: types.Array(typ), 232 Error: errors.New("Failed to get values of `null`"), 233 }, 0, nil 234 } 235 236 m, ok := bind.Value.(map[string]interface{}) 237 if !ok { 238 return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into map") 239 } 240 241 res := make([]interface{}, len(m)) 242 var i int 243 for _, value := range m { 244 res[i] = value 245 i++ 246 } 247 248 return ArrayData(res, typ), 0, nil 249 } 250 251 func dictGetIndexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 252 if bind.Value == nil { 253 return &RawData{Type: bind.Type}, 0, nil 254 } 255 256 switch x := bind.Value.(type) { 257 case []interface{}: 258 args := chunk.Function.Args 259 260 // TODO: all this needs to go into the compile phase 261 if len(args) < 1 { 262 return nil, 0, errors.New("Called [] with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 263 } 264 if len(args) > 1 { 265 return nil, 0, errors.New("Called [] with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 266 } 267 t := types.Type(args[0].Type) 268 if t != types.Int { 269 return nil, 0, errors.New("Called [] with wrong type " + t.Label()) 270 } 271 // ^^ TODO 272 273 key := int(bytes2int(args[0].Value)) 274 return &RawData{ 275 Value: x[key], 276 Type: bind.Type, 277 }, 0, nil 278 279 case map[string]interface{}: 280 args := chunk.Function.Args 281 282 // TODO: all this needs to go into the compile phase 283 if len(args) < 1 { 284 return nil, 0, errors.New("Called [] with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 285 } 286 if len(args) > 1 { 287 return nil, 0, errors.New("Called [] with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 288 } 289 t := types.Type(args[0].Type) 290 if t != types.String { 291 return nil, 0, errors.New("Called [] with wrong type " + t.Label()) 292 } 293 // ^^ TODO 294 295 key := string(args[0].Value) 296 return &RawData{ 297 Value: x[key], 298 Type: bind.Type, 299 }, 0, nil 300 default: 301 return nil, 0, errors.New("dict value does not support accessor `[]`") 302 } 303 } 304 305 func dictGetFirstIndexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 306 if bind.Value == nil { 307 return &RawData{Type: bind.Type}, 0, nil 308 } 309 310 switch x := bind.Value.(type) { 311 case []interface{}: 312 if len(x) == 0 { 313 return &RawData{Type: bind.Type}, 0, nil 314 } 315 316 return &RawData{ 317 Value: x[0], 318 Type: bind.Type, 319 }, 0, nil 320 321 case map[string]interface{}: 322 if len(x) == 0 { 323 return &RawData{Type: bind.Type}, 0, nil 324 } 325 326 var firstKey string 327 for k := range x { 328 firstKey = k 329 break 330 } 331 for k := range x { 332 if k < firstKey { 333 firstKey = k 334 } 335 } 336 337 return &RawData{ 338 Value: x[firstKey], 339 Type: bind.Type, 340 }, 0, nil 341 default: 342 return &RawData{Type: bind.Type}, 0, nil 343 } 344 } 345 346 func dictGetLastIndexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 347 if bind.Value == nil { 348 return &RawData{Type: bind.Type}, 0, nil 349 } 350 351 switch x := bind.Value.(type) { 352 case []interface{}: 353 if len(x) == 0 { 354 return &RawData{Type: bind.Type}, 0, nil 355 } 356 357 return &RawData{ 358 Value: x[len(x)-1], 359 Type: bind.Type, 360 }, 0, nil 361 362 case map[string]interface{}: 363 if len(x) == 0 { 364 return &RawData{Type: bind.Type}, 0, nil 365 } 366 367 var lastKey string 368 for k := range x { 369 lastKey = k 370 break 371 } 372 for k := range x { 373 if lastKey < k { 374 lastKey = k 375 } 376 } 377 378 return &RawData{ 379 Value: x[lastKey], 380 Type: bind.Type, 381 }, 0, nil 382 default: 383 return &RawData{Type: bind.Type}, 0, nil 384 } 385 } 386 387 func dictLengthV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 388 if bind.Value == nil { 389 return &RawData{Type: bind.Type}, 0, nil 390 } 391 392 switch x := bind.Value.(type) { 393 case string: 394 return IntData(int64(len(x))), 0, nil 395 case []interface{}: 396 return IntData(int64(len(x))), 0, nil 397 case map[string]interface{}: 398 return IntData(int64(len(x))), 0, nil 399 default: 400 return nil, 0, errors.New("dict value does not support field `length`") 401 } 402 } 403 404 func dictCmpEmpty(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 405 if bind.Value == nil { 406 return BoolTrue, 0, nil 407 } 408 409 switch x := bind.Value.(type) { 410 case string: 411 return BoolData(len(x) == 0), 0, nil 412 case []interface{}: 413 return BoolData(len(x) == 0), 0, nil 414 case map[string]interface{}: 415 return BoolData(len(x) == 0), 0, nil 416 default: 417 return BoolFalse, 0, nil 418 } 419 } 420 421 func dictNotEmpty(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 422 if bind.Value == nil { 423 return BoolFalse, 0, nil 424 } 425 426 switch x := bind.Value.(type) { 427 case string: 428 return BoolData(len(x) != 0), 0, nil 429 case []interface{}: 430 return BoolData(len(x) != 0), 0, nil 431 case map[string]interface{}: 432 return BoolData(len(x) != 0), 0, nil 433 default: 434 return BoolTrue, 0, nil 435 } 436 } 437 438 // Deprecated: replace with calls to the empty type 439 func dictNotEmptyV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 440 if bind.Value == nil { 441 return BoolFalse, 0, nil 442 } 443 444 switch x := bind.Value.(type) { 445 case string: 446 return BoolData(len(x) != 0), 0, nil 447 case []interface{}: 448 return BoolData(len(x) != 0), 0, nil 449 case map[string]interface{}: 450 return BoolData(len(x) != 0), 0, nil 451 default: 452 return nil, 0, errors.New("dict value does not support field `notEmpty`") 453 } 454 } 455 456 func dictBlockCallV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 457 switch bind.Value.(type) { 458 case []interface{}: 459 return arrayBlockListV2(e, bind, chunk, ref) 460 default: 461 return e.runBlock(bind, chunk.Function.Args[0], chunk.Function.Args[1:], ref) 462 } 463 } 464 465 func dictCamelcaseV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 466 _, ok := bind.Value.(string) 467 if !ok { 468 return nil, 0, errors.New("dict value does not support field `downcase`") 469 } 470 471 return stringCamelcaseV2(e, bind, chunk, ref) 472 } 473 474 func dictDowncaseV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 475 _, ok := bind.Value.(string) 476 if !ok { 477 return nil, 0, errors.New("dict value does not support field `downcase`") 478 } 479 480 return stringDowncaseV2(e, bind, chunk, ref) 481 } 482 483 func dictUpcaseV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 484 _, ok := bind.Value.(string) 485 if !ok { 486 return nil, 0, errors.New("dict value does not support field `upcase`") 487 } 488 489 return stringUpcaseV2(e, bind, chunk, ref) 490 } 491 492 func dictLinesV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 493 _, ok := bind.Value.(string) 494 if !ok { 495 return nil, 0, errors.New("dict value does not support field `lines`") 496 } 497 498 return stringLinesV2(e, bind, chunk, ref) 499 } 500 501 func dictSplitV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 502 _, ok := bind.Value.(string) 503 if !ok { 504 return nil, 0, errors.New("dict value does not support field `split`") 505 } 506 507 return stringSplitV2(e, bind, chunk, ref) 508 } 509 510 func dictTrimV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 511 _, ok := bind.Value.(string) 512 if !ok { 513 return nil, 0, errors.New("dict value does not support field `trim`") 514 } 515 516 return stringTrimV2(e, bind, chunk, ref) 517 } 518 519 func dictKeysV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 520 if bind.Value == nil { 521 return &RawData{ 522 Type: types.Array(types.Dict), 523 Error: errors.New("Failed to get keys of `null`"), 524 }, 0, nil 525 } 526 527 m, ok := bind.Value.(map[string]interface{}) 528 if !ok { 529 return nil, 0, errors.New("dict value does not support field `keys`") 530 } 531 532 res := make([]interface{}, len(m)) 533 var i int 534 for key := range m { 535 res[i] = key 536 i++ 537 } 538 539 return ArrayData(res, types.String), 0, nil 540 } 541 542 func dictValuesV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 543 if bind.Value == nil { 544 return &RawData{ 545 Type: types.Array(types.Dict), 546 Error: errors.New("Failed to get values of `null`"), 547 }, 0, nil 548 } 549 550 m, ok := bind.Value.(map[string]interface{}) 551 if !ok { 552 return nil, 0, errors.New("dict value does not support field `values`") 553 } 554 555 res := make([]interface{}, len(m)) 556 var i int 557 for _, value := range m { 558 res[i] = value 559 i++ 560 } 561 562 return ArrayData(res, types.Dict), 0, nil 563 } 564 565 // Where blocks on strings try to see if the content is found inside the string. 566 // Due to the way the compiler behaves, if we check for static values, it is 567 // converted into a function: 568 // 569 // "hello".contains("ll") ==> "hello".contains( _ == "ll" ) 570 // 571 // ie: "hello".where("ll") ==> "hello".where(_ == "ll") = "ll" 572 // 573 // This means that we do not treat these operations the same we would for equality. 574 // This is why the operations need a bit of special handling, which is done 575 // inside this function. 576 func _stringWhere(e *blockExecutor, src string, chunk *Chunk, ref uint64, inverted bool) (*RawData, uint64, error) { 577 arg1 := chunk.Function.Args[1] 578 fref, ok := arg1.RefV2() 579 if !ok { 580 return nil, 0, errors.New("Failed to retrieve function reference of 'where' call") 581 } 582 583 dref, err := e.ensureArgsResolved(chunk.Function.Args[2:], ref) 584 if dref != 0 || err != nil { 585 return nil, dref, err 586 } 587 588 funBlock := e.ctx.code.Block(fref) 589 if len(funBlock.Chunks) == 0 { 590 return BoolFalse, 0, nil 591 } 592 593 var found *RawResult 594 err = e.runFunctionBlock([]*RawData{ 595 {Type: types.Nil, Value: nil}, 596 {Type: types.StringSlice, Value: src}, 597 }, fref, func(res *RawResult) { 598 found = res 599 }) 600 601 return found.Data, 0, nil 602 } 603 604 // requires at least 1 entry in the list! 605 func _dictArrayWhere(e *blockExecutor, list []interface{}, chunk *Chunk, ref uint64, invert bool) (*RawData, uint64, error) { 606 arg1 := chunk.Function.Args[1] 607 fref, ok := arg1.RefV2() 608 if !ok { 609 return nil, 0, errors.New("Failed to retrieve function reference of 'where' call") 610 } 611 612 dref, err := e.ensureArgsResolved(chunk.Function.Args[2:], ref) 613 if dref != 0 || err != nil { 614 return nil, dref, err 615 } 616 617 argsList := make([][]*RawData, len(list)) 618 for i, value := range list { 619 argsList[i] = []*RawData{ 620 { 621 Type: types.Dict, 622 Value: i, 623 }, 624 { 625 Type: types.Dict, 626 Value: value, 627 }, 628 } 629 } 630 631 err = e.runFunctionBlocks(argsList, fref, func(results []arrayBlockCallResult, errs []error) { 632 resList := []interface{}{} 633 for i, res := range results { 634 if res.isTruthy() == !invert { 635 key := argsList[i][0].Value.(int) 636 resList = append(resList, list[key]) 637 } 638 } 639 640 data := &RawData{ 641 Type: types.Dict, 642 Value: resList, 643 } 644 e.cache.Store(ref, &stepCache{ 645 Result: data, 646 IsStatic: false, 647 }) 648 e.triggerChain(ref, data) 649 }) 650 651 if err != nil { 652 return nil, 0, err 653 } 654 655 return nil, 0, nil 656 } 657 658 func _dictWhereV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64, invert bool) (*RawData, uint64, error) { 659 itemsRef := chunk.Function.Args[0] 660 items, rref, err := e.resolveValue(itemsRef, ref) 661 if err != nil || rref > 0 { 662 return nil, rref, err 663 } 664 665 if items.Value == nil { 666 return &RawData{Type: items.Type}, 0, nil 667 } 668 669 if s, ok := items.Value.(string); ok { 670 return _stringWhere(e, s, chunk, ref, invert) 671 } 672 673 if list, ok := items.Value.([]interface{}); ok { 674 if len(list) == 0 { 675 return items, 0, nil 676 } 677 return _dictArrayWhere(e, list, chunk, ref, invert) 678 } 679 680 list, ok := items.Value.(map[string]interface{}) 681 if !ok { 682 return nil, 0, errors.New("failed to call dict.where on this value") 683 } 684 if len(list) == 0 { 685 return items, 0, nil 686 } 687 688 arg1 := chunk.Function.Args[1] 689 if types.Type(arg1.Type).Underlying() != types.FunctionLike { 690 return nil, 0, errors.New("cannot call 'where' on a map without a filter function") 691 } 692 693 fref, ok := arg1.RefV2() 694 if !ok { 695 return nil, 0, errors.New("failed to retrieve function reference of 'where' call") 696 } 697 698 dref, err := e.ensureArgsResolved(chunk.Function.Args[2:], ref) 699 if dref != 0 || err != nil { 700 return nil, dref, err 701 } 702 703 valueType := items.Type.Child() 704 705 argsList := make([][]*RawData, len(list)) 706 i := 0 707 for key, value := range list { 708 argsList[i] = []*RawData{ 709 { 710 Type: types.Dict, 711 Value: key, 712 }, 713 { 714 Type: valueType, 715 Value: value, 716 }, 717 } 718 i++ 719 } 720 721 err = e.runFunctionBlocks(argsList, fref, func(results []arrayBlockCallResult, errs []error) { 722 resMap := map[string]interface{}{} 723 for i, res := range results { 724 if res.isTruthy() == !invert { 725 key := argsList[i][0].Value.(string) 726 resMap[key] = list[key] 727 } 728 } 729 data := &RawData{ 730 Type: bind.Type, 731 Value: resMap, 732 } 733 e.cache.Store(ref, &stepCache{ 734 Result: data, 735 IsStatic: false, 736 }) 737 e.triggerChain(ref, data) 738 }) 739 740 if err != nil { 741 return nil, 0, err 742 } 743 744 return nil, 0, nil 745 } 746 747 func dictWhereV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 748 return _dictWhereV2(e, bind, chunk, ref, false) 749 } 750 751 func dictWhereNotV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 752 return _dictWhereV2(e, bind, chunk, ref, true) 753 } 754 755 func dictAllV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 756 if bind.Value == nil { 757 return &RawData{Type: types.Bool}, 0, nil 758 } 759 760 if filteredList, ok := bind.Value.([]interface{}); ok { 761 if len(filteredList) == 0 { 762 return BoolTrue, 0, nil 763 } 764 return BoolFalse, 0, nil 765 } 766 767 if filteredList, ok := bind.Value.(map[string]interface{}); ok { 768 if len(filteredList) == 0 { 769 return BoolTrue, 0, nil 770 } 771 return BoolFalse, 0, nil 772 } 773 774 return nil, 0, errors.New("failed to call dict assertion on a non-list/map value") 775 } 776 777 func dictNoneV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 778 if bind.Value == nil { 779 return &RawData{Type: types.Bool}, 0, nil 780 } 781 782 if filteredList, ok := bind.Value.([]interface{}); ok { 783 if len(filteredList) == 0 { 784 return BoolTrue, 0, nil 785 } 786 return BoolFalse, 0, nil 787 } 788 789 if filteredList, ok := bind.Value.(map[string]interface{}); ok { 790 if len(filteredList) == 0 { 791 return BoolTrue, 0, nil 792 } 793 return BoolFalse, 0, nil 794 } 795 796 return nil, 0, errors.New("failed to call dict assertion on a non-list/map value") 797 } 798 799 func dictAnyV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 800 if bind.Value == nil { 801 return &RawData{Type: types.Bool}, 0, nil 802 } 803 804 if filteredList, ok := bind.Value.([]interface{}); ok { 805 if len(filteredList) != 0 { 806 return BoolTrue, 0, nil 807 } 808 return BoolFalse, 0, nil 809 } 810 811 if filteredList, ok := bind.Value.(map[string]interface{}); ok { 812 if len(filteredList) != 0 { 813 return BoolTrue, 0, nil 814 } 815 return BoolFalse, 0, nil 816 } 817 818 return nil, 0, errors.New("failed to call dict assertion on a non-list/map value") 819 } 820 821 func dictOneV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 822 if bind.Value == nil { 823 return &RawData{Type: types.Bool}, 0, nil 824 } 825 826 if filteredList, ok := bind.Value.([]interface{}); ok { 827 if len(filteredList) == 1 { 828 return BoolTrue, 0, nil 829 } 830 return BoolFalse, 0, nil 831 } 832 833 if filteredList, ok := bind.Value.(map[string]interface{}); ok { 834 if len(filteredList) == 1 { 835 return BoolTrue, 0, nil 836 } 837 return BoolFalse, 0, nil 838 } 839 840 return nil, 0, errors.New("failed to call dict assertion on a non-list/map value") 841 } 842 843 func dictMapV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 844 // map(array, function) 845 itemsRef := chunk.Function.Args[0] 846 items, rref, err := e.resolveValue(itemsRef, ref) 847 if err != nil || rref > 0 { 848 return nil, rref, err 849 } 850 851 if items.Value == nil { 852 return &RawData{Type: items.Type}, 0, nil 853 } 854 855 list, ok := items.Value.([]interface{}) 856 if !ok { 857 return nil, 0, errors.New("failed to call dict.map on a non-list value") 858 } 859 860 if len(list) == 0 { 861 return items, 0, nil 862 } 863 864 arg1 := chunk.Function.Args[1] 865 fref, ok := arg1.RefV2() 866 if !ok { 867 return nil, 0, errors.New("Failed to retrieve function reference of 'map' call") 868 } 869 870 dref, err := e.ensureArgsResolved(chunk.Function.Args[2:], ref) 871 if dref != 0 || err != nil { 872 return nil, dref, err 873 } 874 875 ct := items.Type.Child() 876 mappedType := types.Unset 877 resMap := map[int]interface{}{} 878 finishedResults := 0 879 l := sync.Mutex{} 880 for it := range list { 881 i := it 882 err := e.runFunctionBlock([]*RawData{{Type: ct, Value: list[i]}}, fref, func(res *RawResult) { 883 resList := func() []interface{} { 884 l.Lock() 885 defer l.Unlock() 886 887 _, ok := resMap[i] 888 if !ok { 889 finishedResults++ 890 resMap[i] = res.Data.Value 891 mappedType = res.Data.Type 892 } 893 894 if finishedResults == len(list) { 895 resList := []interface{}{} 896 for j := 0; j < len(resMap); j++ { 897 k := resMap[j] 898 if k != nil { 899 resList = append(resList, k) 900 } 901 } 902 return resList 903 } 904 return nil 905 }() 906 907 if resList != nil { 908 data := &RawData{ 909 Type: types.Array(mappedType), 910 Value: resList, 911 } 912 e.cache.Store(ref, &stepCache{ 913 Result: data, 914 IsStatic: false, 915 }) 916 e.triggerChain(ref, data) 917 } 918 }) 919 if err != nil { 920 return nil, 0, err 921 } 922 } 923 924 return nil, 0, nil 925 } 926 927 func dictFlat(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 928 if bind.Value == nil { 929 return &RawData{Type: bind.Type, Error: bind.Error}, 0, nil 930 } 931 932 list, ok := bind.Value.([]interface{}) 933 // this should not happen at this point 934 if !ok { 935 return &RawData{Type: bind.Type, Error: errors.New("incorrect type, no array data found")}, 0, nil 936 } 937 938 var res []interface{} 939 for i := range list { 940 res = append(res, flatten(list[i])...) 941 } 942 943 return &RawData{Type: bind.Type.Child(), Value: res}, 0, nil 944 } 945 946 func dictDifferenceV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 947 if bind.Value == nil { 948 return &RawData{Type: bind.Type, Error: bind.Error}, 0, nil 949 } 950 951 args := chunk.Function.Args 952 // TODO: all this needs to go into the compile phase 953 if len(args) < 1 { 954 return nil, 0, errors.New("Called `difference` with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 955 } 956 if len(args) > 1 { 957 return nil, 0, errors.New("called `difference` with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 958 } 959 // ^^ TODO 960 961 argRef := args[0] 962 arg, rref, err := e.resolveValue(argRef, ref) 963 if err != nil || rref > 0 { 964 return nil, rref, err 965 } 966 967 org, ok := bind.Value.([]interface{}) 968 if !ok { 969 return &RawData{Type: bind.Type, Error: errors.New("cannot compute difference of lists, argument is not a list")}, 0, nil 970 } 971 972 filters, ok := arg.Value.([]interface{}) 973 if !ok { 974 return &RawData{Type: bind.Type, Error: errors.New("tried to call function with a non-array, please make sure the argument is an array")}, 0, nil 975 } 976 977 var res []interface{} 978 var skip bool 979 for i := range org { 980 skip = false 981 for j := range filters { 982 if org[i] == filters[j] { 983 skip = true 984 break 985 } 986 } 987 988 if !skip { 989 res = append(res, org[i]) 990 } 991 } 992 993 return &RawData{Type: bind.Type, Value: res}, 0, nil 994 } 995 996 func dictContainsNoneV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 997 if bind.Value == nil { 998 return &RawData{Type: bind.Type, Error: bind.Error}, 0, nil 999 } 1000 1001 args := chunk.Function.Args 1002 // TODO: all this needs to go into the compile phase 1003 if len(args) < 1 { 1004 return nil, 0, errors.New("Called `difference` with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 1005 } 1006 if len(args) > 1 { 1007 return nil, 0, errors.New("called `difference` with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.") 1008 } 1009 // ^^ TODO 1010 1011 argRef := args[0] 1012 arg, rref, err := e.resolveValue(argRef, ref) 1013 if err != nil || rref > 0 { 1014 return nil, rref, err 1015 } 1016 1017 org, ok := bind.Value.([]interface{}) 1018 if !ok { 1019 return &RawData{Type: bind.Type, Error: errors.New("cannot compute difference of lists, argument is not a list")}, 0, nil 1020 } 1021 1022 filters, ok := arg.Value.([]interface{}) 1023 if !ok { 1024 return &RawData{Type: bind.Type, Error: errors.New("tried to call function with a non-array, please make sure the argument is an array")}, 0, nil 1025 // filters = []interface{}{arg.Value} 1026 } 1027 1028 var res []interface{} 1029 var skip bool 1030 for i := range org { 1031 skip = true 1032 for j := range filters { 1033 if org[i] == filters[j] { 1034 skip = false 1035 break 1036 } 1037 } 1038 1039 if !skip { 1040 res = append(res, org[i]) 1041 } 1042 } 1043 1044 return &RawData{Type: bind.Type, Value: res}, 0, nil 1045 } 1046 1047 func anyContainsString(an interface{}, s string) bool { 1048 if an == nil { 1049 return false 1050 } 1051 1052 switch x := an.(type) { 1053 case string: 1054 return strings.Contains(x, s) 1055 case []interface{}: 1056 for i := range x { 1057 if anyContainsString(x[i], s) { 1058 return true 1059 } 1060 } 1061 return false 1062 default: 1063 return false 1064 } 1065 } 1066 1067 func anyContainsRegex(an interface{}, re *regexp.Regexp) bool { 1068 if an == nil { 1069 return false 1070 } 1071 1072 switch x := an.(type) { 1073 case string: 1074 return re.MatchString(x) 1075 case []interface{}: 1076 for i := range x { 1077 if anyContainsRegex(x[i], re) { 1078 return true 1079 } 1080 } 1081 return false 1082 default: 1083 return false 1084 } 1085 } 1086 1087 func dictContainsStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1088 argRef := chunk.Function.Args[0] 1089 arg, rref, err := e.resolveValue(argRef, ref) 1090 if err != nil || rref > 0 { 1091 return nil, rref, err 1092 } 1093 1094 if arg.Value == nil { 1095 return BoolFalse, 0, nil 1096 } 1097 1098 ok := anyContainsString(bind.Value, arg.Value.(string)) 1099 return BoolData(ok), 0, nil 1100 } 1101 1102 func dictContainsIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1103 argRef := chunk.Function.Args[0] 1104 arg, rref, err := e.resolveValue(argRef, ref) 1105 if err != nil || rref > 0 { 1106 return nil, rref, err 1107 } 1108 1109 if arg.Value == nil { 1110 return BoolFalse, 0, nil 1111 } 1112 1113 val := strconv.FormatInt(arg.Value.(int64), 10) 1114 1115 ok := anyContainsString(bind.Value, val) 1116 return BoolData(ok), 0, nil 1117 } 1118 1119 func dictContainsRegex(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1120 argRef := chunk.Function.Args[0] 1121 arg, rref, err := e.resolveValue(argRef, ref) 1122 if err != nil || rref > 0 { 1123 return nil, rref, err 1124 } 1125 1126 if arg.Value == nil { 1127 return BoolFalse, 0, nil 1128 } 1129 1130 reContent := arg.Value.(string) 1131 re, err := regexp.Compile(reContent) 1132 if err != nil { 1133 return nil, 0, errors.New("Failed to compile regular expression: " + reContent) 1134 } 1135 1136 ok := anyContainsRegex(bind.Value, re) 1137 return BoolData(ok), 0, nil 1138 } 1139 1140 func dictContainsArrayStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1141 switch bind.Value.(type) { 1142 case string: 1143 return stringContainsArrayStringV2(e, bind, chunk, ref) 1144 default: 1145 return nil, 0, errors.New("dict value does not support field `contains`") 1146 } 1147 } 1148 1149 func dictContainsArrayIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1150 switch bind.Value.(type) { 1151 case string: 1152 return stringContainsArrayIntV2(e, bind, chunk, ref) 1153 default: 1154 return nil, 0, errors.New("dict value does not support field `contains`") 1155 } 1156 } 1157 1158 func dictContainsArrayRegex(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1159 switch bind.Value.(type) { 1160 case string: 1161 return stringContainsArrayRegex(e, bind, chunk, ref) 1162 default: 1163 return nil, 0, errors.New("dict value does not support field `contains`") 1164 } 1165 } 1166 1167 func dictFindV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1168 switch bind.Value.(type) { 1169 case string: 1170 return stringFindV2(e, bind, chunk, ref) 1171 default: 1172 return nil, 0, errors.New("dict value does not support field `find`") 1173 } 1174 } 1175 1176 // map &&/|| 1177 1178 func opArrayAndMap(left interface{}, right interface{}) bool { 1179 return (len(left.([]interface{})) != 0) && (len(right.(map[string]interface{})) != 0) 1180 } 1181 1182 func opArrayOrMap(left interface{}, right interface{}) bool { 1183 return (len(left.([]interface{})) != 0) || (len(right.(map[string]interface{})) != 0) 1184 } 1185 1186 func opMapAndArray(left interface{}, right interface{}) bool { 1187 return (len(right.(map[string]interface{})) != 0) && (len(left.([]interface{})) != 0) 1188 } 1189 1190 func opMapOrArray(left interface{}, right interface{}) bool { 1191 return (len(right.(map[string]interface{})) != 0) || (len(left.([]interface{})) != 0) 1192 } 1193 1194 func arrayAndMapV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1195 return boolOpV2(e, bind, chunk, ref, opArrayAndMap) 1196 } 1197 1198 func arrayOrMapV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1199 return boolOpV2(e, bind, chunk, ref, opArrayOrMap) 1200 } 1201 1202 func mapAndArrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1203 return boolOpV2(e, bind, chunk, ref, opMapAndArray) 1204 } 1205 1206 func mapOrArrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1207 return boolOpV2(e, bind, chunk, ref, opMapOrArray) 1208 } 1209 1210 func opMapAndMap(left interface{}, right interface{}) bool { 1211 return (len(left.(map[string]interface{})) != 0) && (len(right.(map[string]interface{})) != 0) 1212 } 1213 1214 func opMapOrMap(left interface{}, right interface{}) bool { 1215 return (len(left.(map[string]interface{})) != 0) || (len(right.(map[string]interface{})) != 0) 1216 } 1217 1218 func mapAndMapV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1219 return boolOpV2(e, bind, chunk, ref, opMapAndMap) 1220 } 1221 1222 func mapOrMapV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1223 return boolOpV2(e, bind, chunk, ref, opMapOrMap) 1224 } 1225 1226 // dict ==/!= nil 1227 1228 func opDictCmpNil(left interface{}, right interface{}) bool { 1229 return left == nil 1230 } 1231 1232 func opNilCmpDict(left interface{}, right interface{}) bool { 1233 return right == nil 1234 } 1235 1236 func dictCmpNilV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1237 return boolOpV2(e, bind, chunk, ref, opDictCmpNil) 1238 } 1239 1240 func dictNotNilV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1241 return boolNotOpV2(e, bind, chunk, ref, opDictCmpNil) 1242 } 1243 1244 func nilCmpDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1245 return boolOpV2(e, bind, chunk, ref, opNilCmpDict) 1246 } 1247 1248 func nilNotDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1249 return boolNotOpV2(e, bind, chunk, ref, opNilCmpDict) 1250 } 1251 1252 // dict ==/!= bool 1253 1254 func opDictCmpBool(left interface{}, right interface{}) bool { 1255 switch x := left.(type) { 1256 case bool: 1257 return x == right.(bool) 1258 case string: 1259 return opStringCmpBool(x, right) 1260 default: 1261 return false 1262 } 1263 } 1264 1265 func opBoolCmpDict(left interface{}, right interface{}) bool { 1266 switch x := right.(type) { 1267 case bool: 1268 return left.(bool) == x 1269 case string: 1270 return opBoolCmpString(left, x) 1271 default: 1272 return false 1273 } 1274 } 1275 1276 func dictCmpBoolV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1277 return boolOpV2(e, bind, chunk, ref, opDictCmpBool) 1278 } 1279 1280 func dictNotBoolV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1281 return boolNotOpV2(e, bind, chunk, ref, opDictCmpBool) 1282 } 1283 1284 func boolCmpDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1285 return boolOpV2(e, bind, chunk, ref, opBoolCmpDict) 1286 } 1287 1288 func boolNotDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1289 return boolNotOpV2(e, bind, chunk, ref, opBoolCmpDict) 1290 } 1291 1292 // dict ==/!= int (embedded: string + float) 1293 1294 func opDictCmpInt(left interface{}, right interface{}) bool { 1295 if _, ok := left.(int32); ok { 1296 left = int64(left.(int32)) 1297 } 1298 switch x := left.(type) { 1299 case int64: 1300 return x == right.(int64) 1301 case float64: 1302 return x == float64(right.(int64)) 1303 case string: 1304 return opStringCmpInt(x, right) 1305 default: 1306 return false 1307 } 1308 } 1309 1310 func opIntCmpDict(left interface{}, right interface{}) bool { 1311 if _, ok := right.(int32); ok { 1312 right = int64(right.(int32)) 1313 } 1314 switch x := right.(type) { 1315 case int64: 1316 return left.(int64) == x 1317 case float64: 1318 return float64(left.(int64)) == x 1319 case string: 1320 return opIntCmpString(left, x) 1321 default: 1322 return false 1323 } 1324 } 1325 1326 func dictCmpIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1327 return boolOpV2(e, bind, chunk, ref, opDictCmpInt) 1328 } 1329 1330 func dictNotIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1331 return boolNotOpV2(e, bind, chunk, ref, opDictCmpInt) 1332 } 1333 1334 func intCmpDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1335 return boolOpV2(e, bind, chunk, ref, opIntCmpDict) 1336 } 1337 1338 func intNotDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1339 return boolNotOpV2(e, bind, chunk, ref, opIntCmpDict) 1340 } 1341 1342 // dict ==/!= float 1343 1344 func opDictCmpFloat(left interface{}, right interface{}) bool { 1345 switch x := left.(type) { 1346 case int64: 1347 return float64(x) == right.(float64) 1348 case float64: 1349 return x == right.(float64) 1350 case string: 1351 return opStringCmpFloat(x, right) 1352 default: 1353 return false 1354 } 1355 } 1356 1357 func opFloatCmpDict(left interface{}, right interface{}) bool { 1358 switch x := right.(type) { 1359 case int64: 1360 return left.(float64) == float64(x) 1361 case float64: 1362 return left.(float64) == x 1363 case string: 1364 return opFloatCmpString(left, x) 1365 default: 1366 return false 1367 } 1368 } 1369 1370 func dictCmpFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1371 return boolOpV2(e, bind, chunk, ref, opDictCmpFloat) 1372 } 1373 1374 func dictNotFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1375 return boolNotOpV2(e, bind, chunk, ref, opDictCmpFloat) 1376 } 1377 1378 func floatCmpDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1379 return boolOpV2(e, bind, chunk, ref, opFloatCmpDict) 1380 } 1381 1382 func floatNotDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1383 return boolNotOpV2(e, bind, chunk, ref, opFloatCmpDict) 1384 } 1385 1386 // dict ==/!= string 1387 1388 func opDictCmpString(left interface{}, right interface{}) bool { 1389 switch x := left.(type) { 1390 case string: 1391 return x == right.(string) 1392 case bool: 1393 return opBoolCmpString(x, right) 1394 case int64: 1395 return opIntCmpString(x, right) 1396 case float64: 1397 return opFloatCmpString(x, right) 1398 default: 1399 return false 1400 } 1401 } 1402 1403 func opStringCmpDict(left interface{}, right interface{}) bool { 1404 switch x := right.(type) { 1405 case string: 1406 return left.(string) == x 1407 case bool: 1408 return opStringCmpBool(left, x) 1409 case int64: 1410 return opStringCmpInt(left, x) 1411 case float64: 1412 return opStringCmpFloat(left, x) 1413 default: 1414 return false 1415 } 1416 } 1417 1418 func dictCmpStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1419 return boolOpV2(e, bind, chunk, ref, opDictCmpString) 1420 } 1421 1422 func dictNotStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1423 return boolNotOpV2(e, bind, chunk, ref, opDictCmpString) 1424 } 1425 1426 func stringCmpDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1427 return boolOpV2(e, bind, chunk, ref, opStringCmpDict) 1428 } 1429 1430 func stringNotDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1431 return boolNotOpV2(e, bind, chunk, ref, opStringCmpDict) 1432 } 1433 1434 // dict ==/!= regex 1435 1436 func opDictCmpRegex(left interface{}, right interface{}) bool { 1437 switch x := left.(type) { 1438 case string: 1439 return opStringCmpRegex(x, right) 1440 case int64: 1441 return opIntCmpRegex(x, right) 1442 case float64: 1443 return opFloatCmpRegex(x, right) 1444 default: 1445 return false 1446 } 1447 } 1448 1449 func opRegexCmpDict(left interface{}, right interface{}) bool { 1450 switch x := right.(type) { 1451 case string: 1452 return opRegexCmpString(left, x) 1453 case int64: 1454 return opRegexCmpInt(left, x) 1455 case float64: 1456 return opRegexCmpFloat(left, x) 1457 default: 1458 return false 1459 } 1460 } 1461 1462 func dictCmpRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1463 return boolOpV2(e, bind, chunk, ref, opDictCmpRegex) 1464 } 1465 1466 func dictNotRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1467 return boolNotOpV2(e, bind, chunk, ref, opDictCmpRegex) 1468 } 1469 1470 func regexCmpDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1471 return boolOpV2(e, bind, chunk, ref, opRegexCmpDict) 1472 } 1473 1474 func regexNotDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1475 return boolNotOpV2(e, bind, chunk, ref, opRegexCmpDict) 1476 } 1477 1478 // dict ==/!= arrays 1479 1480 func opDictCmpArray(left interface{}, right interface{}) bool { 1481 switch left.(type) { 1482 case string: 1483 return false 1484 default: 1485 return false 1486 } 1487 } 1488 1489 func dictCmpArrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1490 return boolOpV2(e, bind, chunk, ref, opDictCmpArray) 1491 } 1492 1493 func dictNotArrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1494 return boolNotOpV2(e, bind, chunk, ref, opDictCmpArray) 1495 } 1496 1497 func opDictCmpStringarray(left *RawData, right *RawData) bool { 1498 switch left.Value.(type) { 1499 case string: 1500 return cmpArrayOne(right, left, opStringCmpString) 1501 case []interface{}: 1502 return cmpArrays(left, right, opDictCmpString) 1503 default: 1504 return false 1505 } 1506 } 1507 1508 func dictCmpStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1509 return rawboolOpV2(e, bind, chunk, ref, opDictCmpStringarray) 1510 } 1511 1512 func dictNotStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1513 return rawboolNotOpV2(e, bind, chunk, ref, opDictCmpStringarray) 1514 } 1515 1516 func opDictCmpBoolarray(left *RawData, right *RawData) bool { 1517 switch left.Value.(type) { 1518 case string: 1519 return cmpArrayOne(right, left, opBoolCmpString) 1520 default: 1521 return false 1522 } 1523 } 1524 1525 func dictCmpBoolarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1526 return rawboolOpV2(e, bind, chunk, ref, opDictCmpStringarray) 1527 } 1528 1529 func dictNotBoolarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1530 return rawboolNotOpV2(e, bind, chunk, ref, opDictCmpStringarray) 1531 } 1532 1533 func opDictCmpIntarray(left *RawData, right *RawData) bool { 1534 switch left.Value.(type) { 1535 case string: 1536 return cmpArrayOne(right, left, opIntCmpString) 1537 default: 1538 return false 1539 } 1540 } 1541 1542 func dictCmpIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1543 return rawboolOpV2(e, bind, chunk, ref, opDictCmpIntarray) 1544 } 1545 1546 func dictNotIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1547 return rawboolNotOpV2(e, bind, chunk, ref, opDictCmpIntarray) 1548 } 1549 1550 func opDictCmpFloatarray(left *RawData, right *RawData) bool { 1551 switch left.Value.(type) { 1552 case string: 1553 return cmpArrayOne(right, left, opFloatCmpString) 1554 default: 1555 return false 1556 } 1557 } 1558 1559 func dictCmpFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1560 return rawboolOpV2(e, bind, chunk, ref, opDictCmpFloatarray) 1561 } 1562 1563 func dictNotFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1564 return rawboolNotOpV2(e, bind, chunk, ref, opDictCmpFloatarray) 1565 } 1566 1567 // dict ==/!= dict 1568 1569 func opDictCmpDict(left interface{}, right interface{}) bool { 1570 switch x := left.(type) { 1571 case bool: 1572 return opBoolCmpDict(x, right) 1573 case int64: 1574 return opIntCmpDict(x, right) 1575 case float64: 1576 return opFloatCmpDict(x, right) 1577 case string: 1578 return opStringCmpDict(x, right) 1579 default: 1580 return false 1581 } 1582 } 1583 1584 func dictCmpDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1585 return boolOpV2(e, bind, chunk, ref, opDictCmpDict) 1586 } 1587 1588 func dictNotDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1589 return boolNotOpV2(e, bind, chunk, ref, opDictCmpDict) 1590 } 1591 1592 // dict </>/<=/>= int 1593 1594 func opDictLTInt(left interface{}, right interface{}) *RawData { 1595 switch x := left.(type) { 1596 case int64: 1597 return BoolData(x < right.(int64)) 1598 case float64: 1599 return BoolData(x < float64(right.(int64))) 1600 case string: 1601 f, err := strconv.ParseInt(x, 10, 64) 1602 if err != nil { 1603 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1604 } 1605 return BoolData(f < right.(int64)) 1606 default: 1607 return &RawData{Error: errors.New("type conflict for '<'"), Type: types.Bool} 1608 } 1609 } 1610 1611 func opDictLTEInt(left interface{}, right interface{}) *RawData { 1612 switch x := left.(type) { 1613 case int64: 1614 return BoolData(x <= right.(int64)) 1615 case float64: 1616 return BoolData(x <= float64(right.(int64))) 1617 case string: 1618 f, err := strconv.ParseInt(x, 10, 64) 1619 if err != nil { 1620 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1621 } 1622 return BoolData(f <= right.(int64)) 1623 default: 1624 return &RawData{Error: errors.New("type conflict for '<='"), Type: types.Bool} 1625 } 1626 } 1627 1628 func opDictGTInt(left interface{}, right interface{}) *RawData { 1629 switch x := left.(type) { 1630 case int64: 1631 return BoolData(x > right.(int64)) 1632 case float64: 1633 return BoolData(x > float64(right.(int64))) 1634 case string: 1635 f, err := strconv.ParseInt(x, 10, 64) 1636 if err != nil { 1637 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1638 } 1639 return BoolData(f > right.(int64)) 1640 default: 1641 return &RawData{Error: errors.New("type conflict for '>'"), Type: types.Bool} 1642 } 1643 } 1644 1645 func opDictGTEInt(left interface{}, right interface{}) *RawData { 1646 switch x := left.(type) { 1647 case int64: 1648 return BoolData(x >= right.(int64)) 1649 case float64: 1650 return BoolData(x >= float64(right.(int64))) 1651 case string: 1652 f, err := strconv.ParseInt(x, 10, 64) 1653 if err != nil { 1654 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1655 } 1656 return BoolData(f >= right.(int64)) 1657 default: 1658 return &RawData{Error: errors.New("type conflict for '>='"), Type: types.Bool} 1659 } 1660 } 1661 1662 func dictLTIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1663 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictLTInt) 1664 } 1665 1666 func dictLTEIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1667 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictLTEInt) 1668 } 1669 1670 func dictGTIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1671 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictGTInt) 1672 } 1673 1674 func dictGTEIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1675 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictGTEInt) 1676 } 1677 1678 func opIntLTDict(left interface{}, right interface{}) *RawData { 1679 switch x := right.(type) { 1680 case int64: 1681 return BoolData(left.(int64) < x) 1682 case float64: 1683 return BoolData(float64(left.(int64)) < x) 1684 case string: 1685 f, err := strconv.ParseInt(x, 10, 64) 1686 if err != nil { 1687 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1688 } 1689 return BoolData(left.(int64) < f) 1690 default: 1691 return &RawData{Error: errors.New("type conflict for '<'"), Type: types.Bool} 1692 } 1693 } 1694 1695 func opIntLTEDict(left interface{}, right interface{}) *RawData { 1696 switch x := right.(type) { 1697 case int64: 1698 return BoolData(left.(int64) <= x) 1699 case float64: 1700 return BoolData(float64(left.(int64)) <= x) 1701 case string: 1702 f, err := strconv.ParseInt(x, 10, 64) 1703 if err != nil { 1704 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1705 } 1706 return BoolData(left.(int64) <= f) 1707 default: 1708 return &RawData{Error: errors.New("type conflict for '<='"), Type: types.Bool} 1709 } 1710 } 1711 1712 func opIntGTDict(left interface{}, right interface{}) *RawData { 1713 switch x := right.(type) { 1714 case int64: 1715 return BoolData(left.(int64) > x) 1716 case float64: 1717 return BoolData(float64(left.(int64)) > x) 1718 case string: 1719 f, err := strconv.ParseInt(x, 10, 64) 1720 if err != nil { 1721 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1722 } 1723 return BoolData(left.(int64) > f) 1724 default: 1725 return &RawData{Error: errors.New("type conflict for '>'"), Type: types.Bool} 1726 } 1727 } 1728 1729 func opIntGTEDict(left interface{}, right interface{}) *RawData { 1730 switch x := right.(type) { 1731 case int64: 1732 return BoolData(left.(int64) >= x) 1733 case float64: 1734 return BoolData(float64(left.(int64)) >= x) 1735 case string: 1736 f, err := strconv.ParseInt(x, 10, 64) 1737 if err != nil { 1738 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1739 } 1740 return BoolData(left.(int64) >= f) 1741 default: 1742 return &RawData{Error: errors.New("type conflict for '>='"), Type: types.Bool} 1743 } 1744 } 1745 1746 func intLTDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1747 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opIntLTDict) 1748 } 1749 1750 func intLTEDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1751 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opIntLTEDict) 1752 } 1753 1754 func intGTDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1755 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opIntLTEDict) 1756 } 1757 1758 func intGTEDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1759 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opIntLTDict) 1760 } 1761 1762 // dict </>/<=/>= float 1763 1764 func opDictLTFloat(left interface{}, right interface{}) *RawData { 1765 switch x := left.(type) { 1766 case int64: 1767 return BoolData(float64(x) < right.(float64)) 1768 case float64: 1769 return BoolData(x < right.(float64)) 1770 case string: 1771 f, err := strconv.ParseFloat(x, 64) 1772 if err != nil { 1773 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1774 } 1775 return BoolData(f < right.(float64)) 1776 default: 1777 return &RawData{Error: errors.New("type conflict for '<'"), Type: types.Bool} 1778 } 1779 } 1780 1781 func opDictLTEFloat(left interface{}, right interface{}) *RawData { 1782 switch x := left.(type) { 1783 case int64: 1784 return BoolData(float64(x) <= right.(float64)) 1785 case float64: 1786 return BoolData(x <= right.(float64)) 1787 case string: 1788 f, err := strconv.ParseFloat(x, 64) 1789 if err != nil { 1790 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1791 } 1792 return BoolData(f <= right.(float64)) 1793 default: 1794 return &RawData{Error: errors.New("type conflict for '<='"), Type: types.Bool} 1795 } 1796 } 1797 1798 func opDictGTFloat(left interface{}, right interface{}) *RawData { 1799 switch x := left.(type) { 1800 case int64: 1801 return BoolData(float64(x) > right.(float64)) 1802 case float64: 1803 return BoolData(x > right.(float64)) 1804 case string: 1805 f, err := strconv.ParseFloat(x, 64) 1806 if err != nil { 1807 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1808 } 1809 return BoolData(f > right.(float64)) 1810 default: 1811 return &RawData{Error: errors.New("type conflict for '>'"), Type: types.Bool} 1812 } 1813 } 1814 1815 func opDictGTEFloat(left interface{}, right interface{}) *RawData { 1816 switch x := left.(type) { 1817 case int64: 1818 return BoolData(float64(x) >= right.(float64)) 1819 case float64: 1820 return BoolData(x >= right.(float64)) 1821 case string: 1822 f, err := strconv.ParseFloat(x, 64) 1823 if err != nil { 1824 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1825 } 1826 return BoolData(f >= right.(float64)) 1827 default: 1828 return &RawData{Error: errors.New("type conflict for '>='"), Type: types.Bool} 1829 } 1830 } 1831 1832 func dictLTFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1833 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictLTFloat) 1834 } 1835 1836 func dictLTEFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1837 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictLTEFloat) 1838 } 1839 1840 func dictGTFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1841 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictGTFloat) 1842 } 1843 1844 func dictGTEFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1845 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictGTEFloat) 1846 } 1847 1848 func opFloatLTDict(left interface{}, right interface{}) *RawData { 1849 switch x := right.(type) { 1850 case int64: 1851 return BoolData(left.(float64) < float64(x)) 1852 case float64: 1853 return BoolData(left.(float64) < x) 1854 case string: 1855 f, err := strconv.ParseFloat(x, 64) 1856 if err != nil { 1857 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1858 } 1859 return BoolData(left.(float64) < f) 1860 default: 1861 return &RawData{Error: errors.New("type conflict for '<'"), Type: types.Bool} 1862 } 1863 } 1864 1865 func opFloatLTEDict(left interface{}, right interface{}) *RawData { 1866 switch x := right.(type) { 1867 case int64: 1868 return BoolData(left.(float64) <= float64(x)) 1869 case float64: 1870 return BoolData(left.(float64) <= x) 1871 case string: 1872 f, err := strconv.ParseFloat(x, 64) 1873 if err != nil { 1874 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1875 } 1876 return BoolData(left.(float64) <= f) 1877 default: 1878 return &RawData{Error: errors.New("type conflict for '<='"), Type: types.Bool} 1879 } 1880 } 1881 1882 func opFloatGTDict(left interface{}, right interface{}) *RawData { 1883 switch x := right.(type) { 1884 case int64: 1885 return BoolData(left.(float64) > float64(x)) 1886 case float64: 1887 return BoolData(left.(float64) > x) 1888 case string: 1889 f, err := strconv.ParseFloat(x, 64) 1890 if err != nil { 1891 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1892 } 1893 return BoolData(left.(float64) > f) 1894 default: 1895 return &RawData{Error: errors.New("type conflict for '>'"), Type: types.Bool} 1896 } 1897 } 1898 1899 func opFloatGTEDict(left interface{}, right interface{}) *RawData { 1900 switch x := right.(type) { 1901 case int64: 1902 return BoolData(left.(float64) >= float64(x)) 1903 case float64: 1904 return BoolData(left.(float64) >= x) 1905 case string: 1906 f, err := strconv.ParseFloat(x, 64) 1907 if err != nil { 1908 return &RawData{Error: errors.New("cannot parse " + x + " as number"), Type: types.Bool} 1909 } 1910 return BoolData(left.(float64) >= f) 1911 default: 1912 return &RawData{Error: errors.New("type conflict for '>='"), Type: types.Bool} 1913 } 1914 } 1915 1916 func floatLTDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1917 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opFloatLTDict) 1918 } 1919 1920 func floatLTEDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1921 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opFloatLTEDict) 1922 } 1923 1924 func floatGTDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1925 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opFloatGTDict) 1926 } 1927 1928 func floatGTEDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 1929 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opFloatGTEDict) 1930 } 1931 1932 // dict </>/<=/>= string 1933 1934 func opDictLTString(left interface{}, right interface{}) *RawData { 1935 switch x := left.(type) { 1936 case int64: 1937 f, err := strconv.ParseInt(right.(string), 10, 64) 1938 if err != nil { 1939 return &RawData{Error: errors.New("cannot parse " + right.(string) + " as number"), Type: types.Bool} 1940 } 1941 return BoolData(x < f) 1942 case float64: 1943 f, err := strconv.ParseFloat(right.(string), 64) 1944 if err != nil { 1945 return &RawData{Error: errors.New("cannot parse " + right.(string) + " as number"), Type: types.Bool} 1946 } 1947 return BoolData(x < f) 1948 case string: 1949 return BoolData(x < right.(string)) 1950 default: 1951 return &RawData{Error: errors.New("type conflict for '<'"), Type: types.Bool} 1952 } 1953 } 1954 1955 func opDictLTEString(left interface{}, right interface{}) *RawData { 1956 switch x := left.(type) { 1957 case int64: 1958 f, err := strconv.ParseInt(right.(string), 10, 64) 1959 if err != nil { 1960 return &RawData{Error: errors.New("cannot parse " + right.(string) + " as number"), Type: types.Bool} 1961 } 1962 return BoolData(x <= f) 1963 case float64: 1964 f, err := strconv.ParseFloat(right.(string), 64) 1965 if err != nil { 1966 return &RawData{Error: errors.New("cannot parse " + right.(string) + " as number"), Type: types.Bool} 1967 } 1968 return BoolData(x <= f) 1969 case string: 1970 return BoolData(x <= right.(string)) 1971 default: 1972 return &RawData{Error: errors.New("type conflict for '<='"), Type: types.Bool} 1973 } 1974 } 1975 1976 func opDictGTString(left interface{}, right interface{}) *RawData { 1977 switch x := left.(type) { 1978 case int64: 1979 f, err := strconv.ParseInt(right.(string), 10, 64) 1980 if err != nil { 1981 return &RawData{Error: errors.New("cannot parse " + right.(string) + " as number"), Type: types.Bool} 1982 } 1983 return BoolData(x > f) 1984 case float64: 1985 f, err := strconv.ParseFloat(right.(string), 64) 1986 if err != nil { 1987 return &RawData{Error: errors.New("cannot parse " + right.(string) + " as number"), Type: types.Bool} 1988 } 1989 return BoolData(x > f) 1990 case string: 1991 return BoolData(x > right.(string)) 1992 default: 1993 return &RawData{Error: errors.New("type conflict for '>'"), Type: types.Bool} 1994 } 1995 } 1996 1997 func opDictGTEString(left interface{}, right interface{}) *RawData { 1998 switch x := left.(type) { 1999 case int64: 2000 f, err := strconv.ParseInt(right.(string), 10, 64) 2001 if err != nil { 2002 return &RawData{Error: errors.New("cannot parse " + right.(string) + " as number"), Type: types.Bool} 2003 } 2004 return BoolData(x >= f) 2005 case float64: 2006 f, err := strconv.ParseFloat(right.(string), 64) 2007 if err != nil { 2008 return &RawData{Error: errors.New("cannot parse " + right.(string) + " as number"), Type: types.Bool} 2009 } 2010 return BoolData(x >= f) 2011 case string: 2012 return BoolData(x >= right.(string)) 2013 default: 2014 return &RawData{Error: errors.New("type conflict for '>='"), Type: types.Bool} 2015 } 2016 } 2017 2018 func dictLTStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2019 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictLTString) 2020 } 2021 2022 func dictLTEStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2023 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictLTEString) 2024 } 2025 2026 func dictGTStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2027 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictGTString) 2028 } 2029 2030 func dictGTEStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2031 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opDictGTEString) 2032 } 2033 2034 func opStringLTDict(left interface{}, right interface{}) *RawData { 2035 switch x := right.(type) { 2036 case int64: 2037 f, err := strconv.ParseInt(left.(string), 10, 64) 2038 if err != nil { 2039 return &RawData{Error: errors.New("cannot parse " + left.(string) + " as number"), Type: types.Bool} 2040 } 2041 return BoolData(f < x) 2042 case float64: 2043 f, err := strconv.ParseFloat(left.(string), 64) 2044 if err != nil { 2045 return &RawData{Error: errors.New("cannot parse " + left.(string) + " as number"), Type: types.Bool} 2046 } 2047 return BoolData(f < x) 2048 case string: 2049 return BoolData(left.(string) < x) 2050 default: 2051 return &RawData{Error: errors.New("type conflict for '<'"), Type: types.Bool} 2052 } 2053 } 2054 2055 func opStringLTEDict(left interface{}, right interface{}) *RawData { 2056 switch x := right.(type) { 2057 case int64: 2058 f, err := strconv.ParseInt(left.(string), 10, 64) 2059 if err != nil { 2060 return &RawData{Error: errors.New("cannot parse " + left.(string) + " as number"), Type: types.Bool} 2061 } 2062 return BoolData(f <= x) 2063 case float64: 2064 f, err := strconv.ParseFloat(left.(string), 64) 2065 if err != nil { 2066 return &RawData{Error: errors.New("cannot parse " + left.(string) + " as number"), Type: types.Bool} 2067 } 2068 return BoolData(f <= x) 2069 case string: 2070 return BoolData(left.(string) <= x) 2071 default: 2072 return &RawData{Error: errors.New("type conflict for '<='"), Type: types.Bool} 2073 } 2074 } 2075 2076 func opStringGTDict(left interface{}, right interface{}) *RawData { 2077 switch x := right.(type) { 2078 case int64: 2079 f, err := strconv.ParseInt(left.(string), 10, 64) 2080 if err != nil { 2081 return &RawData{Error: errors.New("cannot parse " + left.(string) + " as number"), Type: types.Bool} 2082 } 2083 return BoolData(f > x) 2084 case float64: 2085 f, err := strconv.ParseFloat(left.(string), 64) 2086 if err != nil { 2087 return &RawData{Error: errors.New("cannot parse " + left.(string) + " as number"), Type: types.Bool} 2088 } 2089 return BoolData(f > x) 2090 case string: 2091 return BoolData(left.(string) > x) 2092 default: 2093 return &RawData{Error: errors.New("type conflict for '>'"), Type: types.Bool} 2094 } 2095 } 2096 2097 func opStringGTEDict(left interface{}, right interface{}) *RawData { 2098 switch x := right.(type) { 2099 case int64: 2100 f, err := strconv.ParseInt(left.(string), 10, 64) 2101 if err != nil { 2102 return &RawData{Error: errors.New("cannot parse " + left.(string) + " as number"), Type: types.Bool} 2103 } 2104 return BoolData(f >= x) 2105 case float64: 2106 f, err := strconv.ParseFloat(left.(string), 64) 2107 if err != nil { 2108 return &RawData{Error: errors.New("cannot parse " + left.(string) + " as number"), Type: types.Bool} 2109 } 2110 return BoolData(f >= x) 2111 case string: 2112 return BoolData(left.(string) >= x) 2113 default: 2114 return &RawData{Error: errors.New("type conflict for '>='"), Type: types.Bool} 2115 } 2116 } 2117 2118 func stringLTDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2119 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opStringLTDict) 2120 } 2121 2122 func stringLTEDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2123 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opStringLTEDict) 2124 } 2125 2126 func stringGTDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2127 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opStringGTDict) 2128 } 2129 2130 func stringGTEDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2131 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, opStringGTEDict) 2132 } 2133 2134 // dict </>/<=/>= dict 2135 2136 func dictLTDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2137 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, func(left interface{}, right interface{}) *RawData { 2138 switch x := right.(type) { 2139 case int64: 2140 return opDictLTInt(left, x) 2141 case float64: 2142 return opDictLTFloat(left, x) 2143 case string: 2144 return opDictLTString(left, x) 2145 default: 2146 return &RawData{Error: errors.New("type conflict for '<'"), Type: types.Bool} 2147 } 2148 }) 2149 } 2150 2151 func dictLTEDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2152 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, func(left interface{}, right interface{}) *RawData { 2153 switch x := right.(type) { 2154 case int64: 2155 return opDictLTEInt(left, x) 2156 case float64: 2157 return opDictLTEFloat(left, x) 2158 case string: 2159 return opDictLTEString(left, x) 2160 default: 2161 return &RawData{Error: errors.New("type conflict for '<='"), Type: types.Bool} 2162 } 2163 }) 2164 } 2165 2166 func dictGTDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2167 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, func(left interface{}, right interface{}) *RawData { 2168 switch x := right.(type) { 2169 case int64: 2170 return opDictLTEInt(left, x) 2171 case float64: 2172 return opDictLTEFloat(left, x) 2173 case string: 2174 return opDictLTString(left, x) 2175 default: 2176 return &RawData{Error: errors.New("type conflict for '>'"), Type: types.Bool} 2177 } 2178 }) 2179 } 2180 2181 func dictGTEDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2182 return nonNilDataOpV2(e, bind, chunk, ref, types.Bool, func(left interface{}, right interface{}) *RawData { 2183 switch x := right.(type) { 2184 case int64: 2185 return opDictLTInt(left, x) 2186 case float64: 2187 return opDictLTFloat(left, x) 2188 case string: 2189 return opDictLTString(left, x) 2190 default: 2191 return &RawData{Error: errors.New("type conflict for '>='"), Type: types.Bool} 2192 } 2193 }) 2194 } 2195 2196 // dict && / || ... 2197 2198 func truthyDict(value interface{}) bool { 2199 switch x := value.(type) { 2200 case bool: 2201 return x 2202 case int64: 2203 return x != 0 2204 case float64: 2205 return x != 0 2206 case string: 2207 return x != "" 2208 case []interface{}: 2209 return len(x) != 0 2210 case map[string]interface{}: 2211 return len(x) != 0 2212 default: 2213 return false 2214 } 2215 } 2216 2217 // ... bool 2218 2219 func opBoolAndDict(left interface{}, right interface{}) bool { 2220 return left.(bool) && truthyDict(right) 2221 } 2222 2223 func opBoolOrDict(left interface{}, right interface{}) bool { 2224 return left.(bool) || truthyDict(right) 2225 } 2226 2227 func opDictAndBool(left interface{}, right interface{}) bool { 2228 return truthyDict(left) && right.(bool) 2229 } 2230 2231 func opDictOrBool(left interface{}, right interface{}) bool { 2232 return truthyDict(left) || right.(bool) 2233 } 2234 2235 func boolAndDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2236 return boolOpV2(e, bind, chunk, ref, opBoolAndDict) 2237 } 2238 2239 func boolOrDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2240 return boolOpV2(e, bind, chunk, ref, opBoolOrDict) 2241 } 2242 2243 func dictAndBoolV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2244 return boolOpV2(e, bind, chunk, ref, opDictAndBool) 2245 } 2246 2247 func dictOrBoolV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2248 return boolOpV2(e, bind, chunk, ref, opDictOrBool) 2249 } 2250 2251 // ... int 2252 2253 func opIntAndDict(left interface{}, right interface{}) bool { 2254 return left.(int64) != 0 && truthyDict(right) 2255 } 2256 2257 func opIntOrDict(left interface{}, right interface{}) bool { 2258 return left.(int64) != 0 || truthyDict(right) 2259 } 2260 2261 func opDictAndInt(left interface{}, right interface{}) bool { 2262 return truthyDict(left) && right.(int64) != 0 2263 } 2264 2265 func opDictOrInt(left interface{}, right interface{}) bool { 2266 return truthyDict(left) || right.(int64) != 0 2267 } 2268 2269 func intAndDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2270 return boolOpV2(e, bind, chunk, ref, opIntAndDict) 2271 } 2272 2273 func intOrDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2274 return boolOpV2(e, bind, chunk, ref, opIntOrDict) 2275 } 2276 2277 func dictAndIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2278 return boolOpV2(e, bind, chunk, ref, opDictAndInt) 2279 } 2280 2281 func dictOrIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2282 return boolOpV2(e, bind, chunk, ref, opDictOrInt) 2283 } 2284 2285 // ... float 2286 2287 func opFloatAndDict(left interface{}, right interface{}) bool { 2288 return left.(float64) != 0 && truthyDict(right) 2289 } 2290 2291 func opFloatOrDict(left interface{}, right interface{}) bool { 2292 return left.(float64) != 0 || truthyDict(right) 2293 } 2294 2295 func opDictAndFloat(left interface{}, right interface{}) bool { 2296 return truthyDict(left) && right.(float64) != 0 2297 } 2298 2299 func opDictOrFloat(left interface{}, right interface{}) bool { 2300 return truthyDict(left) || right.(float64) != 0 2301 } 2302 2303 func floatAndDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2304 return boolOpV2(e, bind, chunk, ref, opFloatAndDict) 2305 } 2306 2307 func floatOrDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2308 return boolOpV2(e, bind, chunk, ref, opFloatOrDict) 2309 } 2310 2311 func dictAndFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2312 return boolOpV2(e, bind, chunk, ref, opDictAndFloat) 2313 } 2314 2315 func dictOrFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2316 return boolOpV2(e, bind, chunk, ref, opDictOrFloat) 2317 } 2318 2319 // ... string 2320 2321 func opStringAndDict(left interface{}, right interface{}) bool { 2322 return left.(string) != "" && truthyDict(right) 2323 } 2324 2325 func opStringOrDict(left interface{}, right interface{}) bool { 2326 return left.(string) != "" || truthyDict(right) 2327 } 2328 2329 func opDictAndString(left interface{}, right interface{}) bool { 2330 return truthyDict(left) && right.(string) != "" 2331 } 2332 2333 func opDictOrString(left interface{}, right interface{}) bool { 2334 return truthyDict(left) || right.(string) != "" 2335 } 2336 2337 func stringAndDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2338 return boolOpV2(e, bind, chunk, ref, opStringAndDict) 2339 } 2340 2341 func stringOrDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2342 return boolOpV2(e, bind, chunk, ref, opStringOrDict) 2343 } 2344 2345 func dictAndStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2346 return boolOpV2(e, bind, chunk, ref, opDictAndString) 2347 } 2348 2349 func dictOrStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2350 return boolOpV2(e, bind, chunk, ref, opDictOrString) 2351 } 2352 2353 // ... regex 2354 2355 func opRegexAndDict(left interface{}, right interface{}) bool { 2356 return left.(string) != "" && truthyDict(right) 2357 } 2358 2359 func opRegexOrDict(left interface{}, right interface{}) bool { 2360 return left.(string) != "" || truthyDict(right) 2361 } 2362 2363 func opDictAndRegex(left interface{}, right interface{}) bool { 2364 return truthyDict(left) && right.(string) != "" 2365 } 2366 2367 func opDictOrRegex(left interface{}, right interface{}) bool { 2368 return truthyDict(left) || right.(string) != "" 2369 } 2370 2371 func regexAndDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2372 return boolOpV2(e, bind, chunk, ref, opRegexAndDict) 2373 } 2374 2375 func regexOrDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2376 return boolOpV2(e, bind, chunk, ref, opRegexOrDict) 2377 } 2378 2379 func dictAndRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2380 return boolOpV2(e, bind, chunk, ref, opDictAndRegex) 2381 } 2382 2383 func dictOrRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2384 return boolOpV2(e, bind, chunk, ref, opDictOrRegex) 2385 } 2386 2387 // ... time 2388 // note: time cannot be falsy 2389 2390 func opTimeAndDict(left interface{}, right interface{}) bool { 2391 return truthyDict(right) 2392 } 2393 2394 func opTimeOrDict(left interface{}, right interface{}) bool { 2395 return true 2396 } 2397 2398 func opDictAndTime(left interface{}, right interface{}) bool { 2399 return truthyDict(left) 2400 } 2401 2402 func opDictOrTime(left interface{}, right interface{}) bool { 2403 return true 2404 } 2405 2406 func timeAndDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2407 return boolOpV2(e, bind, chunk, ref, opTimeAndDict) 2408 } 2409 2410 func timeOrDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2411 return boolOpV2(e, bind, chunk, ref, opTimeOrDict) 2412 } 2413 2414 func dictAndTimeV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2415 return boolOpV2(e, bind, chunk, ref, opDictAndTime) 2416 } 2417 2418 func dictOrTimeV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2419 return boolOpV2(e, bind, chunk, ref, opDictOrTime) 2420 } 2421 2422 // ... dict 2423 2424 func opDictAndDict(left interface{}, right interface{}) bool { 2425 return truthyDict(left) && truthyDict(right) 2426 } 2427 2428 func opDictOrDict(left interface{}, right interface{}) bool { 2429 return truthyDict(left) || truthyDict(right) 2430 } 2431 2432 func dictAndDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2433 return boolOpV2(e, bind, chunk, ref, opDictAndDict) 2434 } 2435 2436 func dictOrDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2437 return boolOpV2(e, bind, chunk, ref, opDictOrDict) 2438 } 2439 2440 // ... array 2441 2442 func opDictAndArray(left interface{}, right interface{}) bool { 2443 return truthyDict(left) && (len(right.([]interface{})) != 0) 2444 } 2445 2446 func opArrayAndDict(left interface{}, right interface{}) bool { 2447 return truthyDict(right) && (len(left.([]interface{})) != 0) 2448 } 2449 2450 func opDictOrArray(left interface{}, right interface{}) bool { 2451 return truthyDict(left) || (len(right.([]interface{})) != 0) 2452 } 2453 2454 func opArrayOrDict(left interface{}, right interface{}) bool { 2455 return truthyDict(right) || (len(left.([]interface{})) != 0) 2456 } 2457 2458 func dictAndArrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2459 return boolOpV2(e, bind, chunk, ref, opDictAndArray) 2460 } 2461 2462 func dictOrArrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2463 return boolOpV2(e, bind, chunk, ref, opDictOrArray) 2464 } 2465 2466 func arrayAndDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2467 return boolOpV2(e, bind, chunk, ref, opArrayAndDict) 2468 } 2469 2470 func arrayOrDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2471 return boolOpV2(e, bind, chunk, ref, opArrayOrDict) 2472 } 2473 2474 // ... map 2475 2476 func opDictAndMap(left interface{}, right interface{}) bool { 2477 return truthyDict(left) && (len(right.(map[string]interface{})) != 0) 2478 } 2479 2480 func opMapAndDict(left interface{}, right interface{}) bool { 2481 return truthyDict(right) && (len(left.(map[string]interface{})) != 0) 2482 } 2483 2484 func opDictOrMap(left interface{}, right interface{}) bool { 2485 return truthyDict(left) || (len(right.(map[string]interface{})) != 0) 2486 } 2487 2488 func opMapOrDict(left interface{}, right interface{}) bool { 2489 return truthyDict(right) || (len(left.(map[string]interface{})) != 0) 2490 } 2491 2492 func dictAndMapV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2493 return boolOpV2(e, bind, chunk, ref, opDictAndMap) 2494 } 2495 2496 func dictOrMapV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2497 return boolOpV2(e, bind, chunk, ref, opDictOrMap) 2498 } 2499 2500 func mapAndDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2501 return boolOpV2(e, bind, chunk, ref, opMapAndDict) 2502 } 2503 2504 func mapOrDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2505 return boolOpV2(e, bind, chunk, ref, opMapOrDict) 2506 } 2507 2508 // dict + - * / 2509 2510 func dictPlusStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2511 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2512 r := right.(string) 2513 2514 switch l := left.(type) { 2515 case string: 2516 return StringData(l + r) 2517 default: 2518 return &RawData{ 2519 Type: types.Nil, 2520 Value: nil, 2521 Error: errors.New("dict value does not support `+` operation with string"), 2522 } 2523 } 2524 }) 2525 } 2526 2527 func stringPlusDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2528 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2529 l := left.(string) 2530 2531 switch r := right.(type) { 2532 case string: 2533 return StringData(l + r) 2534 default: 2535 return &RawData{ 2536 Type: types.Nil, 2537 Value: nil, 2538 Error: errors.New("dict value does not support `+` operation with string"), 2539 } 2540 } 2541 }) 2542 } 2543 2544 func intPlusDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2545 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2546 l := left.(int64) 2547 2548 switch r := right.(type) { 2549 case int64: 2550 return IntData(l + r) 2551 case float64: 2552 return FloatData(float64(l) + r) 2553 default: 2554 return &RawData{ 2555 Type: types.Nil, 2556 Value: nil, 2557 Error: errors.New("right side of `+` operation is not number"), 2558 } 2559 } 2560 }) 2561 } 2562 2563 func dictPlusIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2564 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2565 r := right.(int64) 2566 2567 switch l := left.(type) { 2568 case int64: 2569 return IntData(l + r) 2570 case float64: 2571 return FloatData(l + float64(r)) 2572 default: 2573 return &RawData{ 2574 Type: types.Nil, 2575 Value: nil, 2576 Error: errors.New("left side of `+` operation is not number"), 2577 } 2578 } 2579 }) 2580 } 2581 2582 func floatPlusDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2583 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2584 l := left.(float64) 2585 2586 switch r := right.(type) { 2587 case int64: 2588 return FloatData(l + float64(r)) 2589 case float64: 2590 return FloatData(l + r) 2591 default: 2592 return &RawData{ 2593 Type: types.Nil, 2594 Value: nil, 2595 Error: errors.New("right side of `+` operation is not number"), 2596 } 2597 } 2598 }) 2599 } 2600 2601 func dictPlusFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2602 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2603 r := right.(float64) 2604 2605 switch l := left.(type) { 2606 case int64: 2607 return FloatData(float64(l) + r) 2608 case float64: 2609 return FloatData(l + r) 2610 default: 2611 return &RawData{ 2612 Type: types.Nil, 2613 Value: nil, 2614 Error: errors.New("left side of `+` operation is not number"), 2615 } 2616 } 2617 }) 2618 } 2619 2620 func intMinusDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2621 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2622 l := left.(int64) 2623 2624 switch r := right.(type) { 2625 case int64: 2626 return IntData(l - r) 2627 case float64: 2628 return FloatData(float64(l) - r) 2629 default: 2630 return &RawData{ 2631 Type: types.Nil, 2632 Value: nil, 2633 Error: errors.New("right side of `-` operation is not number"), 2634 } 2635 } 2636 }) 2637 } 2638 2639 func dictMinusIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2640 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2641 r := right.(int64) 2642 2643 switch l := left.(type) { 2644 case int64: 2645 return IntData(l - r) 2646 case float64: 2647 return FloatData(l - float64(r)) 2648 default: 2649 return &RawData{ 2650 Type: types.Nil, 2651 Value: nil, 2652 Error: errors.New("left side of `-` operation is not number"), 2653 } 2654 } 2655 }) 2656 } 2657 2658 func floatMinusDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2659 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2660 l := left.(float64) 2661 2662 switch r := right.(type) { 2663 case int64: 2664 return FloatData(l - float64(r)) 2665 case float64: 2666 return FloatData(l - r) 2667 default: 2668 return &RawData{ 2669 Type: types.Nil, 2670 Value: nil, 2671 Error: errors.New("right side of `-` operation is not number"), 2672 } 2673 } 2674 }) 2675 } 2676 2677 func dictMinusFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2678 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2679 r := right.(float64) 2680 2681 switch l := left.(type) { 2682 case int64: 2683 return FloatData(float64(l) - r) 2684 case float64: 2685 return FloatData(l - r) 2686 default: 2687 return &RawData{ 2688 Type: types.Nil, 2689 Value: nil, 2690 Error: errors.New("left side of `-` operation is not number"), 2691 } 2692 } 2693 }) 2694 } 2695 2696 func intTimesDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2697 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2698 l := left.(int64) 2699 2700 switch r := right.(type) { 2701 case int64: 2702 return IntData(l * r) 2703 case float64: 2704 return FloatData(float64(l) * r) 2705 default: 2706 return &RawData{ 2707 Type: types.Nil, 2708 Value: nil, 2709 Error: errors.New("right side of `*` operation is not number"), 2710 } 2711 } 2712 }) 2713 } 2714 2715 func dictTimesIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2716 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2717 r := right.(int64) 2718 2719 switch l := left.(type) { 2720 case int64: 2721 return IntData(l * r) 2722 case float64: 2723 return FloatData(l * float64(r)) 2724 default: 2725 return &RawData{ 2726 Type: types.Nil, 2727 Value: nil, 2728 Error: errors.New("left side of `*` operation is not number"), 2729 } 2730 } 2731 }) 2732 } 2733 2734 func floatTimesDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2735 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2736 l := left.(float64) 2737 2738 switch r := right.(type) { 2739 case int64: 2740 return FloatData(l * float64(r)) 2741 case float64: 2742 return FloatData(l * r) 2743 default: 2744 return &RawData{ 2745 Type: types.Nil, 2746 Value: nil, 2747 Error: errors.New("right side of `*` operation is not number"), 2748 } 2749 } 2750 }) 2751 } 2752 2753 func dictTimesFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2754 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2755 r := right.(float64) 2756 2757 switch l := left.(type) { 2758 case int64: 2759 return FloatData(float64(l) * r) 2760 case float64: 2761 return FloatData(l * r) 2762 default: 2763 return &RawData{ 2764 Type: types.Nil, 2765 Value: nil, 2766 Error: errors.New("left side of `*` operation is not number"), 2767 } 2768 } 2769 }) 2770 } 2771 2772 func intDividedDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2773 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2774 l := left.(int64) 2775 2776 switch r := right.(type) { 2777 case int64: 2778 return IntData(l / r) 2779 case float64: 2780 return FloatData(float64(l) / r) 2781 default: 2782 return &RawData{ 2783 Type: types.Nil, 2784 Value: nil, 2785 Error: errors.New("right side of `/` operation is not number"), 2786 } 2787 } 2788 }) 2789 } 2790 2791 func dictDividedIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2792 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2793 r := right.(int64) 2794 2795 switch l := left.(type) { 2796 case int64: 2797 return IntData(l / r) 2798 case float64: 2799 return FloatData(l / float64(r)) 2800 default: 2801 return &RawData{ 2802 Type: types.Nil, 2803 Value: nil, 2804 Error: errors.New("left side of `/` operation is not number"), 2805 } 2806 } 2807 }) 2808 } 2809 2810 func floatDividedDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2811 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2812 l := left.(float64) 2813 2814 switch r := right.(type) { 2815 case int64: 2816 return FloatData(l / float64(r)) 2817 case float64: 2818 return FloatData(l / r) 2819 default: 2820 return &RawData{ 2821 Type: types.Nil, 2822 Value: nil, 2823 Error: errors.New("right side of `/` operation is not number"), 2824 } 2825 } 2826 }) 2827 } 2828 2829 func dictDividedFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2830 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2831 r := right.(float64) 2832 2833 switch l := left.(type) { 2834 case int64: 2835 return FloatData(float64(l) / r) 2836 case float64: 2837 return FloatData(l / r) 2838 default: 2839 return &RawData{ 2840 Type: types.Nil, 2841 Value: nil, 2842 Error: errors.New("left side of `/` operation is not number"), 2843 } 2844 } 2845 }) 2846 } 2847 2848 func dictTimesTimeV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2849 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2850 switch l := left.(type) { 2851 case int64: 2852 return opTimeTimesInt(right, l) 2853 case float64: 2854 return opTimeTimesFloat(right, l) 2855 default: 2856 return &RawData{ 2857 Type: types.Nil, 2858 Value: nil, 2859 Error: errors.New("left side of `*` operation is not compatible with `time`"), 2860 } 2861 } 2862 }) 2863 } 2864 2865 func timeTimesDictV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) { 2866 return dataOpV2(e, bind, chunk, ref, types.Time, func(left interface{}, right interface{}) *RawData { 2867 switch r := right.(type) { 2868 case int64: 2869 return opTimeTimesInt(left, r) 2870 case float64: 2871 return opTimeTimesFloat(left, r) 2872 default: 2873 return &RawData{ 2874 Type: types.Nil, 2875 Value: nil, 2876 Error: errors.New("left side of `*` operation is not compatible with `time`"), 2877 } 2878 } 2879 }) 2880 }