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  }