go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/llx/builtin_array.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package llx
     5  
     6  import (
     7  	"errors"
     8  	"strconv"
     9  
    10  	"go.mondoo.com/cnquery/types"
    11  	"go.mondoo.com/cnquery/utils/multierr"
    12  )
    13  
    14  var arrayBlockType = types.Array(types.Block)
    15  
    16  // arrayFunctions are all the handlers for builtin array methods
    17  var arrayFunctions map[string]chunkHandlerV2
    18  
    19  func arrayGetFirstIndexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
    20  	if bind.Value == nil {
    21  		return &RawData{Type: bind.Type[1:]}, 0, nil
    22  	}
    23  
    24  	arr, ok := bind.Value.([]interface{})
    25  	if !ok {
    26  		return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into array")
    27  	}
    28  
    29  	if len(arr) == 0 {
    30  		return &RawData{Type: bind.Type[1:]}, 0, nil
    31  	}
    32  
    33  	return &RawData{
    34  		Type:  bind.Type[1:],
    35  		Value: arr[0],
    36  	}, 0, nil
    37  }
    38  
    39  func arrayGetLastIndexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
    40  	if bind.Value == nil {
    41  		return &RawData{Type: bind.Type[1:]}, 0, nil
    42  	}
    43  
    44  	arr, ok := bind.Value.([]interface{})
    45  	if !ok {
    46  		return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into array")
    47  	}
    48  
    49  	if len(arr) == 0 {
    50  		return &RawData{Type: bind.Type[1:]}, 0, nil
    51  	}
    52  
    53  	return &RawData{
    54  		Type:  bind.Type[1:],
    55  		Value: arr[len(arr)-1],
    56  	}, 0, nil
    57  }
    58  
    59  func arrayGetIndexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
    60  	if bind.Value == nil {
    61  		return &RawData{Type: bind.Type[1:]}, 0, nil
    62  	}
    63  
    64  	args := chunk.Function.Args
    65  	// TODO: all this needs to go into the compile phase
    66  	if len(args) < 1 {
    67  		return nil, 0, errors.New("Called [] with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.")
    68  	}
    69  	if len(args) > 1 {
    70  		return nil, 0, errors.New("called [] with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.")
    71  	}
    72  	t := types.Type(args[0].Type)
    73  	if t != types.Int {
    74  		return nil, 0, errors.New("called [] with wrong type " + t.Label())
    75  	}
    76  	// ^^ TODO
    77  
    78  	key := int(bytes2int(args[0].Value))
    79  
    80  	arr, ok := bind.Value.([]interface{})
    81  	if !ok {
    82  		return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into array")
    83  	}
    84  
    85  	if key < 0 {
    86  		if -key > len(arr) {
    87  			return nil, 0, errors.New("array index out of bound (trying to access element " + strconv.Itoa(key) + ", max: " + strconv.Itoa(len(arr)-1) + ")")
    88  		}
    89  		key = len(arr) + key
    90  	}
    91  	if key >= len(arr) {
    92  		return nil, 0, errors.New("array index out of bound (trying to access element " + strconv.Itoa(key) + ", max: " + strconv.Itoa(len(arr)-1) + ")")
    93  	}
    94  
    95  	return &RawData{
    96  		Type:  bind.Type[1:],
    97  		Value: arr[key],
    98  	}, 0, nil
    99  }
   100  
   101  func arrayBlockListV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   102  	if bind.Value == nil {
   103  		return &RawData{Type: bind.Type[1:]}, 0, nil
   104  	}
   105  
   106  	arr, ok := bind.Value.([]interface{})
   107  	if !ok {
   108  		return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into array")
   109  	}
   110  
   111  	if len(arr) == 0 {
   112  		return &RawData{
   113  			Type:  arrayBlockType,
   114  			Value: []interface{}{},
   115  		}, 0, nil
   116  	}
   117  
   118  	prim := chunk.Function.Args[0]
   119  	if !types.Type(prim.Type).IsFunction() {
   120  		return nil, 0, errors.New("called block with wrong function type")
   121  	}
   122  	fref, ok := prim.RefV2()
   123  	if !ok {
   124  		return nil, 0, errors.New("cannot retrieve function reference on block call")
   125  	}
   126  	block := e.ctx.code.Block(fref)
   127  	if block == nil {
   128  		return nil, 0, errors.New("block function is nil")
   129  	}
   130  
   131  	dref, err := e.ensureArgsResolved(chunk.Function.Args[1:], ref)
   132  	if dref != 0 || err != nil {
   133  		return nil, dref, err
   134  	}
   135  
   136  	argList := make([][]*RawData, len(arr))
   137  	for i := range arr {
   138  		argList[i] = []*RawData{
   139  			{
   140  				Type:  bind.Type.Child(),
   141  				Value: arr[i],
   142  			},
   143  		}
   144  	}
   145  
   146  	err = e.runFunctionBlocks(argList, fref, func(results []arrayBlockCallResult, errs []error) {
   147  		// This is quite heavy handed. If any of the block calls have an error, the whole
   148  		// thing becomes errored. If we don't do this, then we can have more fine grained
   149  		// errors. For example, if only one item in the list has errors, the block for that
   150  		// item will have an entrypoint with an error
   151  		var anyError multierr.Errors
   152  		anyError.Add(errs...)
   153  
   154  		allResults := make([]interface{}, len(arr))
   155  		for i, rd := range results {
   156  			allResults[i] = rd.toRawData().Value
   157  		}
   158  
   159  		data := &RawData{
   160  			Type:  arrayBlockType,
   161  			Value: allResults,
   162  			Error: anyError.Deduplicate(),
   163  		}
   164  		e.cache.Store(ref, &stepCache{
   165  			Result:   data,
   166  			IsStatic: true,
   167  		})
   168  		e.triggerChain(ref, data)
   169  	})
   170  
   171  	if err != nil {
   172  		return nil, 0, err
   173  	}
   174  
   175  	return nil, 0, nil
   176  }
   177  
   178  func arrayBlockV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   179  	prim := chunk.Function.Args[0]
   180  	if !types.Type(prim.Type).IsFunction() {
   181  		return nil, 0, errors.New("called block with wrong function type")
   182  	}
   183  	return e.runBlock(bind, prim, chunk.Function.Args[1:], ref)
   184  }
   185  
   186  func arrayLengthV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   187  	if bind.Value == nil {
   188  		return &RawData{Type: types.Int, Error: bind.Error}, 0, nil
   189  	}
   190  
   191  	arr, ok := bind.Value.([]interface{})
   192  	if !ok {
   193  		return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into array")
   194  	}
   195  	return IntData(int64(len(arr))), 0, nil
   196  }
   197  
   198  func arrayNotEmptyV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   199  	if bind.Value == nil {
   200  		return BoolFalse, 0, nil
   201  	}
   202  
   203  	arr, ok := bind.Value.([]interface{})
   204  	if !ok {
   205  		return nil, 0, errors.New("failed to typecast " + bind.Type.Label() + " into array")
   206  	}
   207  
   208  	if len(arr) == 0 {
   209  		return BoolFalse, 0, nil
   210  	}
   211  	return BoolTrue, 0, nil
   212  }
   213  
   214  func _arrayWhereV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64, invert bool) (*RawData, uint64, error) {
   215  	// where(array, function)
   216  	itemsRef := chunk.Function.Args[0]
   217  	items, rref, err := e.resolveValue(itemsRef, ref)
   218  	if err != nil || rref > 0 {
   219  		return nil, rref, err
   220  	}
   221  
   222  	if items.Value == nil {
   223  		return &RawData{Type: items.Type}, 0, nil
   224  	}
   225  
   226  	list := items.Value.([]interface{})
   227  	if len(list) == 0 {
   228  		return items, 0, nil
   229  	}
   230  
   231  	arg1 := chunk.Function.Args[1]
   232  	if types.Type(arg1.Type).Underlying() != types.FunctionLike {
   233  		right := arg1.RawData().Value
   234  		var res []interface{}
   235  		for i := range list {
   236  			left := list[i]
   237  			if left == right {
   238  				res = append(res, left)
   239  			}
   240  		}
   241  
   242  		return &RawData{
   243  			Type:  items.Type,
   244  			Value: res,
   245  		}, 0, nil
   246  	}
   247  
   248  	fref, ok := arg1.RefV2()
   249  	if !ok {
   250  		return nil, 0, errors.New("Failed to retrieve function reference of 'where' call")
   251  	}
   252  
   253  	dref, err := e.ensureArgsResolved(chunk.Function.Args[2:], ref)
   254  	if dref != 0 || err != nil {
   255  		return nil, dref, err
   256  	}
   257  
   258  	ct := items.Type.Child()
   259  
   260  	argsList := make([][]*RawData, len(list))
   261  	for i := range list {
   262  		argsList[i] = []*RawData{
   263  			{
   264  				Type:  ct,
   265  				Value: list[i],
   266  			},
   267  		}
   268  	}
   269  	err = e.runFunctionBlocks(argsList, fref, func(results []arrayBlockCallResult, errors []error) {
   270  		resList := []interface{}{}
   271  		for i, res := range results {
   272  			isTruthy := res.isTruthy()
   273  			if isTruthy == !invert {
   274  				resList = append(resList, list[i])
   275  			}
   276  		}
   277  
   278  		data := &RawData{
   279  			Type:  bind.Type,
   280  			Value: resList,
   281  		}
   282  		e.cache.Store(ref, &stepCache{
   283  			Result:   data,
   284  			IsStatic: false,
   285  		})
   286  		e.triggerChain(ref, data)
   287  	})
   288  
   289  	if err != nil {
   290  		return nil, 0, err
   291  	}
   292  
   293  	return nil, 0, nil
   294  }
   295  
   296  func arrayWhereV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   297  	return _arrayWhereV2(e, bind, chunk, ref, false)
   298  }
   299  
   300  func arrayWhereNotV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   301  	return _arrayWhereV2(e, bind, chunk, ref, true)
   302  }
   303  
   304  func arrayAllV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   305  	if bind.Value == nil {
   306  		return &RawData{Type: types.Bool, Error: errors.New("failed to validate all entries (list is null)")}, 0, nil
   307  	}
   308  
   309  	filteredList := bind.Value.([]interface{})
   310  
   311  	if len(filteredList) != 0 {
   312  		return BoolFalse, 0, nil
   313  	}
   314  	return BoolTrue, 0, nil
   315  }
   316  
   317  func arrayNoneV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   318  	if bind.Value == nil {
   319  		return &RawData{Type: types.Bool, Error: errors.New("failed to validate all entries (list is null)")}, 0, nil
   320  	}
   321  
   322  	filteredList := bind.Value.([]interface{})
   323  
   324  	if len(filteredList) != 0 {
   325  		return BoolFalse, 0, nil
   326  	}
   327  	return BoolTrue, 0, nil
   328  }
   329  
   330  func arrayAnyV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   331  	if bind.Value == nil {
   332  		return &RawData{Type: types.Bool, Error: errors.New("failed to validate all entries (list is null)")}, 0, nil
   333  	}
   334  
   335  	filteredList := bind.Value.([]interface{})
   336  
   337  	if len(filteredList) == 0 {
   338  		return BoolFalse, 0, nil
   339  	}
   340  	return BoolTrue, 0, nil
   341  }
   342  
   343  func arrayOneV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   344  	if bind.Value == nil {
   345  		return &RawData{Type: types.Bool, Error: errors.New("failed to validate all entries (list is null)")}, 0, nil
   346  	}
   347  
   348  	filteredList := bind.Value.([]interface{})
   349  
   350  	if len(filteredList) != 1 {
   351  		return BoolFalse, 0, nil
   352  	}
   353  	return BoolTrue, 0, nil
   354  }
   355  
   356  func arrayMapV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   357  	// map(array, function)
   358  	itemsRef := chunk.Function.Args[0]
   359  	items, rref, err := e.resolveValue(itemsRef, ref)
   360  	if err != nil || rref > 0 {
   361  		return nil, rref, err
   362  	}
   363  
   364  	if items.Value == nil {
   365  		return &RawData{Type: items.Type}, 0, nil
   366  	}
   367  
   368  	list := items.Value.([]interface{})
   369  	if len(list) == 0 {
   370  		return items, 0, nil
   371  	}
   372  
   373  	arg1 := chunk.Function.Args[1]
   374  	fref, ok := arg1.RefV2()
   375  	if !ok {
   376  		return nil, 0, errors.New("Failed to retrieve function reference of 'map' call")
   377  	}
   378  
   379  	dref, err := e.ensureArgsResolved(chunk.Function.Args[2:], ref)
   380  	if dref != 0 || err != nil {
   381  		return nil, dref, err
   382  	}
   383  
   384  	ct := items.Type.Child()
   385  
   386  	argsList := make([][]*RawData, len(list))
   387  	for i := range list {
   388  		argsList[i] = []*RawData{
   389  			{
   390  				Type:  ct,
   391  				Value: list[i],
   392  			},
   393  		}
   394  	}
   395  
   396  	err = e.runFunctionBlocks(argsList, fref, func(results []arrayBlockCallResult, errs []error) {
   397  		mappedType := types.Unset
   398  		resList := []interface{}{}
   399  		f := e.ctx.code.Block(fref)
   400  
   401  		epChecksum := e.ctx.code.Checksums[f.Entrypoints[0]]
   402  
   403  		for _, res := range results {
   404  			if epValIface, ok := res.entrypoints[epChecksum]; ok {
   405  				epVal := epValIface.(*RawData)
   406  				mappedType = epVal.Type
   407  				resList = append(resList, epVal.Value)
   408  			}
   409  		}
   410  
   411  		data := &RawData{
   412  			Type:  types.Array(mappedType),
   413  			Value: resList,
   414  		}
   415  		e.cache.Store(ref, &stepCache{
   416  			Result:   data,
   417  			IsStatic: false,
   418  		})
   419  		e.triggerChain(ref, data)
   420  	})
   421  
   422  	if err != nil {
   423  		return nil, 0, err
   424  	}
   425  
   426  	return nil, 0, nil
   427  }
   428  
   429  func flatten(v interface{}) []interface{} {
   430  	list, ok := v.([]interface{})
   431  	if !ok {
   432  		return []interface{}{v}
   433  	}
   434  
   435  	var res []interface{}
   436  	for i := range list {
   437  		res = append(res, flatten(list[i])...)
   438  	}
   439  	return res
   440  }
   441  
   442  func arrayFlat(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   443  	if bind.Value == nil {
   444  		return &RawData{Type: bind.Type, Error: bind.Error}, 0, nil
   445  	}
   446  
   447  	list, ok := bind.Value.([]interface{})
   448  	// this should not happen at this point
   449  	if !ok {
   450  		return &RawData{Type: bind.Type, Error: errors.New("incorrect type, no array data found")}, 0, nil
   451  	}
   452  
   453  	var res []interface{}
   454  	for i := range list {
   455  		res = append(res, flatten(list[i])...)
   456  	}
   457  
   458  	typ := bind.Type
   459  	for typ.IsArray() {
   460  		typ = typ.Child()
   461  	}
   462  
   463  	return &RawData{Type: types.Array(typ), Value: res}, 0, nil
   464  }
   465  
   466  // Take an array and separate it into a list of unique entries and another
   467  // list of only duplicates. The latter list only has every entry appear only
   468  // once.
   469  func detectDupes(array interface{}, typ types.Type) ([]interface{}, []interface{}, error) {
   470  	if array == nil {
   471  		return nil, nil, nil
   472  	}
   473  	arr, ok := array.([]interface{})
   474  	if !ok {
   475  		return nil, nil, errors.New("failed to typecast " + typ.Label() + " into array")
   476  	}
   477  
   478  	ct := typ.Child()
   479  	equalFunc, ok := types.Equal[ct]
   480  	if !ok {
   481  		return nil, nil, errors.New("cannot extract duplicates from array, must be a basic type. Try using a field argument.")
   482  	}
   483  
   484  	existing := []interface{}{}
   485  	duplicates := []interface{}{}
   486  	var found bool
   487  	for i := 0; i < len(arr); i++ {
   488  		left := arr[i]
   489  
   490  		for j := range existing {
   491  			if equalFunc(left, existing[j]) {
   492  				found = true
   493  				break
   494  			}
   495  		}
   496  
   497  		if !found {
   498  			existing = append(existing, left)
   499  			continue
   500  		}
   501  
   502  		found = false
   503  		for j := range duplicates {
   504  			if equalFunc(left, duplicates[j]) {
   505  				found = true
   506  				break
   507  			}
   508  		}
   509  
   510  		if found {
   511  			found = false
   512  		} else {
   513  			duplicates = append(duplicates, left)
   514  		}
   515  	}
   516  
   517  	return existing, duplicates, nil
   518  }
   519  
   520  // Takes an array of resources and a field, identify duplicates of that field value
   521  // Result list is every resource that has duplicates
   522  // (there will be at least resources 2 if there is a duplicate field value)
   523  func arrayFieldDuplicatesV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   524  	// where(array, function)
   525  	itemsRef := chunk.Function.Args[0]
   526  	items, rref, err := e.resolveValue(itemsRef, ref)
   527  	if err != nil || rref > 0 {
   528  		return nil, rref, err
   529  	}
   530  
   531  	if items.Value == nil {
   532  		return &RawData{Type: items.Type}, 0, nil
   533  	}
   534  
   535  	list := items.Value.([]interface{})
   536  	if len(list) == 0 {
   537  		return items, 0, nil
   538  	}
   539  
   540  	arg1 := chunk.Function.Args[1]
   541  	if types.Type(arg1.Type).Underlying() != types.FunctionLike {
   542  		return nil, 0, errors.New("Expected resource field, unable to get field value from " + types.Type(arg1.Type).Label())
   543  	}
   544  
   545  	fref, ok := arg1.RefV2()
   546  	if !ok {
   547  		return nil, 0, errors.New("Failed to retrieve function reference of 'field duplicates' call")
   548  	}
   549  
   550  	dref, err := e.ensureArgsResolved(chunk.Function.Args[2:], ref)
   551  	if dref != 0 || err != nil {
   552  		return nil, dref, err
   553  	}
   554  
   555  	ct := items.Type.Child()
   556  
   557  	argsList := make([][]*RawData, len(list))
   558  	for i := range list {
   559  		argsList[i] = []*RawData{
   560  			{
   561  				Type:  ct,
   562  				Value: list[i],
   563  			},
   564  		}
   565  	}
   566  
   567  	err = e.runFunctionBlocks(argsList, fref, func(results []arrayBlockCallResult, errs []error) {
   568  		f := e.ctx.code.Block(fref)
   569  		epChecksum := e.ctx.code.Checksums[f.Entrypoints[0]]
   570  		filteredList := map[int]*RawData{}
   571  
   572  		for i, res := range results {
   573  			rd := res.toRawData()
   574  			if rd.Error != nil {
   575  				filteredList[i] = &RawData{
   576  					Error: rd.Error,
   577  				}
   578  			} else {
   579  				epVal := res.entrypoints[epChecksum].(*RawData)
   580  				filteredList[i] = epVal
   581  			}
   582  		}
   583  
   584  		resList := []interface{}{}
   585  
   586  		equalFunc, ok := types.Equal[filteredList[0].Type]
   587  		if !ok {
   588  			data := &RawData{
   589  				Type:  items.Type,
   590  				Error: errors.New("cannot extract duplicates from array, field must be a basic type"),
   591  			}
   592  			e.cache.Store(ref, &stepCache{
   593  				Result:   data,
   594  				IsStatic: false,
   595  			})
   596  			e.triggerChain(ref, data)
   597  			return
   598  		}
   599  
   600  		arr := make([]*RawData, len(list))
   601  		for k, v := range filteredList {
   602  			arr[k] = v
   603  		}
   604  
   605  		// to track values of fields
   606  		existing := make(map[int]interface{})
   607  		// to track index of duplicate resources
   608  		duplicateIndices := []int{}
   609  		var found bool
   610  		var added bool
   611  		for i := 0; i < len(arr); i++ {
   612  			left := arr[i].Value
   613  
   614  			for j, v := range existing {
   615  				if equalFunc(left, v) {
   616  					found = true
   617  					// Track the index so that we can get the whole resource
   618  					duplicateIndices = append(duplicateIndices, i)
   619  					// check if j was already added to our list of indices
   620  					for di := range duplicateIndices {
   621  						if j == duplicateIndices[di] {
   622  							added = true
   623  						}
   624  					}
   625  					if added == false {
   626  						duplicateIndices = append(duplicateIndices, j)
   627  					}
   628  					break
   629  				}
   630  			}
   631  
   632  			// value not found so we add it to list of things to check for dupes
   633  			if !found {
   634  				existing[i] = left
   635  			}
   636  		}
   637  
   638  		// Once we collect duplicate indices, make a list of resources
   639  		for i := range duplicateIndices {
   640  			idx := duplicateIndices[i]
   641  			resList = append(resList, list[idx])
   642  		}
   643  
   644  		data := &RawData{
   645  			Type:  bind.Type,
   646  			Value: resList,
   647  		}
   648  		e.cache.Store(ref, &stepCache{
   649  			Result:   data,
   650  			IsStatic: false,
   651  		})
   652  		e.triggerChain(ref, data)
   653  	})
   654  
   655  	if err != nil {
   656  		return nil, 0, err
   657  	}
   658  
   659  	return nil, 0, nil
   660  }
   661  
   662  func arrayDuplicatesV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   663  	if bind.Value == nil {
   664  		return &RawData{Type: bind.Type, Error: bind.Error}, 0, nil
   665  	}
   666  
   667  	_, dupes, err := detectDupes(bind.Value, bind.Type)
   668  	if err != nil {
   669  		return nil, 0, err
   670  	}
   671  
   672  	return &RawData{Type: bind.Type, Value: dupes}, 0, nil
   673  }
   674  
   675  func arrayUniqueV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   676  	if bind.Value == nil {
   677  		return &RawData{Type: bind.Type, Error: bind.Error}, 0, nil
   678  	}
   679  
   680  	unique, _, err := detectDupes(bind.Value, bind.Type)
   681  	if err != nil {
   682  		return nil, 0, err
   683  	}
   684  
   685  	return &RawData{Type: bind.Type, Value: unique}, 0, nil
   686  }
   687  
   688  func arrayDifferenceV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   689  	if bind.Value == nil {
   690  		return &RawData{Type: bind.Type, Error: bind.Error}, 0, nil
   691  	}
   692  
   693  	args := chunk.Function.Args
   694  	// TODO: all this needs to go into the compile phase
   695  	if len(args) < 1 {
   696  		return nil, 0, errors.New("Called `difference` with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.")
   697  	}
   698  	if len(args) > 1 {
   699  		return nil, 0, errors.New("called `difference` with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.")
   700  	}
   701  	// ^^ TODO
   702  
   703  	argRef := args[0]
   704  	arg, rref, err := e.resolveValue(argRef, ref)
   705  	if err != nil || rref > 0 {
   706  		return nil, rref, err
   707  	}
   708  
   709  	t := types.Type(arg.Type)
   710  	if t != bind.Type {
   711  		return nil, 0, errors.New("called `difference` with wrong type (got: " + t.Label() + ", expected:" + bind.Type.Label() + ")")
   712  	}
   713  
   714  	ct := bind.Type.Child()
   715  	equalFunc, ok := types.Equal[ct]
   716  	if !ok {
   717  		return nil, 0, errors.New("cannot compare array entries")
   718  	}
   719  
   720  	org := bind.Value.([]interface{})
   721  	filters := arg.Value.([]interface{})
   722  
   723  	var res []interface{}
   724  	var skip bool
   725  	for i := range org {
   726  		skip = false
   727  		for j := range filters {
   728  			if equalFunc(org[i], filters[j]) {
   729  				skip = true
   730  				break
   731  			}
   732  		}
   733  
   734  		if !skip {
   735  			res = append(res, org[i])
   736  		}
   737  	}
   738  
   739  	return &RawData{Type: bind.Type, Value: res}, 0, nil
   740  }
   741  
   742  func arrayContainsNoneV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   743  	if bind.Value == nil {
   744  		return &RawData{Type: bind.Type, Error: bind.Error}, 0, nil
   745  	}
   746  
   747  	args := chunk.Function.Args
   748  	// TODO: all this needs to go into the compile phase
   749  	if len(args) < 1 {
   750  		return nil, 0, errors.New("Called `arrayContainsNone` with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.")
   751  	}
   752  	if len(args) > 1 {
   753  		return nil, 0, errors.New("called `arrayContainsNone` with " + strconv.Itoa(len(args)) + " arguments, only 1 supported.")
   754  	}
   755  	// ^^ TODO
   756  
   757  	argRef := args[0]
   758  	arg, rref, err := e.resolveValue(argRef, ref)
   759  	if err != nil || rref > 0 {
   760  		return nil, rref, err
   761  	}
   762  
   763  	t := types.Type(arg.Type)
   764  	if t != bind.Type {
   765  		return nil, 0, errors.New("called `arrayNone` with wrong type (got: " + t.Label() + ", expected:" + bind.Type.Label() + ")")
   766  	}
   767  
   768  	ct := bind.Type.Child()
   769  	equalFunc, ok := types.Equal[ct]
   770  	if !ok {
   771  		return nil, 0, errors.New("cannot compare array entries")
   772  	}
   773  
   774  	org := bind.Value.([]interface{})
   775  	filters := arg.Value.([]interface{})
   776  
   777  	var res []interface{}
   778  	for i := range org {
   779  		for j := range filters {
   780  			if equalFunc(org[i], filters[j]) {
   781  				res = append(res, org[i])
   782  			}
   783  		}
   784  	}
   785  
   786  	return &RawData{Type: bind.Type, Value: res}, 0, nil
   787  }
   788  
   789  func compileArrayOpArray(op string) func(types.Type, types.Type) (string, error) {
   790  	return func(left types.Type, right types.Type) (string, error) {
   791  		name := string(left.Child()) + op + string(right)
   792  		af := BuiltinFunctionsV2[types.ArrayLike]
   793  		if _, ok := af[name]; ok {
   794  			return name, nil
   795  		}
   796  
   797  		if right.IsArray() {
   798  			return op, nil
   799  		}
   800  
   801  		if right == types.Nil {
   802  			return op + string(types.Nil), nil
   803  		}
   804  
   805  		return "", errors.New("don't know how to compile " + left.Label() + " " + op + " " + right.Label())
   806  	}
   807  }
   808  
   809  func compileLogicalArrayOp(underlying types.Type, op string) func(types.Type, types.Type) (string, error) {
   810  	return func(left types.Type, right types.Type) (string, error) {
   811  		name := string(types.Any) + op + string(right.Underlying())
   812  		af := BuiltinFunctionsV2[underlying]
   813  		if _, ok := af[name]; ok {
   814  			return name, nil
   815  		}
   816  
   817  		return "", errors.New("cannot find operation for " + left.Label() + " " + op + " " + right.Label())
   818  	}
   819  }
   820  
   821  func cmpArrays(left *RawData, right *RawData, f func(interface{}, interface{}) bool) bool {
   822  	if left.Value == nil {
   823  		if right.Value == nil {
   824  			return true
   825  		}
   826  		return false
   827  	}
   828  	if right == nil || right.Value == nil {
   829  		return false
   830  	}
   831  
   832  	l := left.Value.([]interface{})
   833  	r := right.Value.([]interface{})
   834  
   835  	if len(l) != len(r) {
   836  		return false
   837  	}
   838  
   839  	for i := range l {
   840  		if !f(l[i], r[i]) {
   841  			return false
   842  		}
   843  	}
   844  
   845  	return true
   846  }
   847  
   848  func cmpArrayOne(leftArray *RawData, right *RawData, f func(interface{}, interface{}) bool) bool {
   849  	l := leftArray.Value.([]interface{})
   850  	if len(l) != 1 {
   851  		return false
   852  	}
   853  	return f(l[0], right.Value)
   854  }
   855  
   856  // []T -- []T
   857  
   858  func tArrayCmp(left *RawData, right *RawData) func(interface{}, interface{}) bool {
   859  	return func(a interface{}, b interface{}) bool {
   860  		if left.Type.Child() != right.Type.Child() {
   861  			return false
   862  		}
   863  		return a == b
   864  	}
   865  }
   866  
   867  func tarrayCmpTarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   868  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
   869  		return cmpArrays(left, right, tArrayCmp(left, right))
   870  	})
   871  }
   872  
   873  func tarrayNotTarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   874  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
   875  		return cmpArrays(left, right, tArrayCmp(left, right))
   876  	})
   877  }
   878  
   879  func tarrayConcatTarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   880  	itemsRef := chunk.Function.Args[0]
   881  	items, rref, err := e.resolveValue(itemsRef, ref)
   882  	if err != nil || rref > 0 {
   883  		return nil, rref, err
   884  	}
   885  
   886  	if items.Value == nil {
   887  		return &RawData{Type: items.Type}, 0, nil
   888  	}
   889  
   890  	v, _ := bind.Value.([]interface{})
   891  	if v == nil {
   892  		if items.Value == nil {
   893  			return &RawData{Type: bind.Type}, 0, nil
   894  		}
   895  		return nil, 0, errors.New("cannot add arrays to null")
   896  	}
   897  
   898  	list := items.Value.([]interface{})
   899  	if len(list) == 0 {
   900  		return items, 0, nil
   901  	}
   902  
   903  	res := make([]interface{}, len(v)+len(list))
   904  	var idx int
   905  	for i := range v {
   906  		res[idx] = v[i]
   907  		idx++
   908  	}
   909  	for i := range list {
   910  		res[idx] = list[i]
   911  		idx++
   912  	}
   913  
   914  	return &RawData{
   915  		Type:  bind.Type,
   916  		Value: res,
   917  	}, 0, nil
   918  }
   919  
   920  func tarrayDeleteTarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   921  	itemsRef := chunk.Function.Args[0]
   922  	items, rref, err := e.resolveValue(itemsRef, ref)
   923  	if err != nil || rref > 0 {
   924  		return nil, rref, err
   925  	}
   926  
   927  	if items.Value == nil {
   928  		return &RawData{Type: items.Type}, 0, nil
   929  	}
   930  
   931  	v, _ := bind.Value.([]interface{})
   932  	if v == nil {
   933  		if items.Value == nil {
   934  			return &RawData{Type: bind.Type}, 0, nil
   935  		}
   936  		return nil, 0, errors.New("cannot add arrays to null")
   937  	}
   938  
   939  	list := items.Value.([]interface{})
   940  	if len(list) == 0 {
   941  		return items, 0, nil
   942  	}
   943  
   944  	// TODO: We can optimize the way the deletion works, but need to map to
   945  	// recognized types to do so. Common example: strings an numbers.
   946  
   947  	res := []interface{}{}
   948  	for i := range v {
   949  		found := false
   950  		for j := range list {
   951  			if v[i] == list[j] {
   952  				found = true
   953  				break
   954  			}
   955  		}
   956  
   957  		if !found {
   958  			res = append(res, v[i])
   959  		}
   960  	}
   961  
   962  	return &RawData{
   963  		Type:  bind.Type,
   964  		Value: res,
   965  	}, 0, nil
   966  }
   967  
   968  func boolarrayCmpBoolarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   969  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
   970  		return cmpArrays(left, right, opBoolCmpBool)
   971  	})
   972  }
   973  
   974  func intarrayCmpIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   975  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
   976  		return cmpArrays(left, right, opIntCmpInt)
   977  	})
   978  }
   979  
   980  func floatarrayCmpFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   981  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
   982  		return cmpArrays(left, right, opFloatCmpFloat)
   983  	})
   984  }
   985  
   986  func stringarrayCmpStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   987  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
   988  		return cmpArrays(left, right, opStringCmpString)
   989  	})
   990  }
   991  
   992  func boolarrayNotBoolarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   993  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
   994  		return cmpArrays(left, right, opBoolCmpBool)
   995  	})
   996  }
   997  
   998  func intarrayNotIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
   999  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1000  		return cmpArrays(left, right, opIntCmpInt)
  1001  	})
  1002  }
  1003  
  1004  func floatarrayNotFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1005  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1006  		return cmpArrays(left, right, opFloatCmpFloat)
  1007  	})
  1008  }
  1009  
  1010  func stringarrayNotStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1011  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1012  		return cmpArrays(left, right, opStringCmpString)
  1013  	})
  1014  }
  1015  
  1016  // []T -- T
  1017  
  1018  func arrayCmpNilV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1019  	if bind.Value == nil {
  1020  		return BoolTrue, 0, nil
  1021  	}
  1022  	v := bind.Value.([]interface{})
  1023  	if v == nil {
  1024  		return BoolTrue, 0, nil
  1025  	}
  1026  	return BoolFalse, 0, nil
  1027  }
  1028  
  1029  func arrayNotNilV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1030  	if bind.Value == nil {
  1031  		return BoolFalse, 0, nil
  1032  	}
  1033  	v := bind.Value.([]interface{})
  1034  	if v == nil {
  1035  		return BoolFalse, 0, nil
  1036  	}
  1037  	return BoolTrue, 0, nil
  1038  }
  1039  
  1040  func arrayCmpEmpty(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1041  	if bind.Value == nil {
  1042  		return BoolTrue, 0, nil
  1043  	}
  1044  	v := bind.Value.([]interface{})
  1045  	if v == nil {
  1046  		return BoolTrue, 0, nil
  1047  	}
  1048  	return BoolData(len(v) == 0), 0, nil
  1049  }
  1050  
  1051  func arrayNotEmpty(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1052  	if bind.Value == nil {
  1053  		return BoolFalse, 0, nil
  1054  	}
  1055  	v := bind.Value.([]interface{})
  1056  	if v == nil {
  1057  		return BoolFalse, 0, nil
  1058  	}
  1059  	return BoolData(len(v) != 0), 0, nil
  1060  }
  1061  
  1062  func boolarrayCmpBoolV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1063  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1064  		return cmpArrayOne(left, right, opBoolCmpBool)
  1065  	})
  1066  }
  1067  
  1068  func boolarrayNotBoolV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1069  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1070  		return cmpArrayOne(left, right, opBoolCmpBool)
  1071  	})
  1072  }
  1073  
  1074  func intarrayCmpIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1075  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1076  		return cmpArrayOne(left, right, opIntCmpInt)
  1077  	})
  1078  }
  1079  
  1080  func intarrayNotIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1081  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1082  		return cmpArrayOne(left, right, opIntCmpInt)
  1083  	})
  1084  }
  1085  
  1086  func floatarrayCmpFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1087  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1088  		return cmpArrayOne(left, right, opFloatCmpFloat)
  1089  	})
  1090  }
  1091  
  1092  func floatarrayNotFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1093  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1094  		return cmpArrayOne(left, right, opFloatCmpFloat)
  1095  	})
  1096  }
  1097  
  1098  func stringarrayCmpStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1099  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1100  		return cmpArrayOne(left, right, opStringCmpString)
  1101  	})
  1102  }
  1103  
  1104  func stringarrayNotStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1105  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1106  		return cmpArrayOne(left, right, opStringCmpString)
  1107  	})
  1108  }
  1109  
  1110  // T -- []T
  1111  
  1112  func boolCmpBoolarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1113  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1114  		return cmpArrayOne(right, left, opBoolCmpBool)
  1115  	})
  1116  }
  1117  
  1118  func boolNotBoolarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1119  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1120  		return cmpArrayOne(right, left, opBoolCmpBool)
  1121  	})
  1122  }
  1123  
  1124  func intCmpIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1125  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1126  		return cmpArrayOne(right, left, opIntCmpInt)
  1127  	})
  1128  }
  1129  
  1130  func intNotIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1131  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1132  		return cmpArrayOne(right, left, opIntCmpInt)
  1133  	})
  1134  }
  1135  
  1136  func floatCmpFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1137  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1138  		return cmpArrayOne(right, left, opFloatCmpFloat)
  1139  	})
  1140  }
  1141  
  1142  func floatNotFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1143  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1144  		return cmpArrayOne(right, left, opFloatCmpFloat)
  1145  	})
  1146  }
  1147  
  1148  func stringCmpStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1149  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1150  		return cmpArrayOne(right, left, opStringCmpString)
  1151  	})
  1152  }
  1153  
  1154  func stringNotStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1155  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1156  		return cmpArrayOne(right, left, opStringCmpString)
  1157  	})
  1158  }
  1159  
  1160  // int/float -- []T
  1161  
  1162  func intCmpFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1163  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1164  		return cmpArrayOne(right, left, opFloatCmpInt)
  1165  	})
  1166  }
  1167  
  1168  func intNotFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1169  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1170  		return cmpArrayOne(right, left, opFloatCmpInt)
  1171  	})
  1172  }
  1173  
  1174  func floatCmpIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1175  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1176  		return cmpArrayOne(right, left, opIntCmpFloat)
  1177  	})
  1178  }
  1179  
  1180  func floatNotIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1181  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1182  		return cmpArrayOne(right, left, opIntCmpFloat)
  1183  	})
  1184  }
  1185  
  1186  func intarrayCmpFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1187  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1188  		return cmpArrayOne(left, right, opIntCmpFloat)
  1189  	})
  1190  }
  1191  
  1192  func intarrayNotFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1193  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1194  		return cmpArrayOne(left, right, opIntCmpFloat)
  1195  	})
  1196  }
  1197  
  1198  func floatarrayCmpIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1199  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1200  		return cmpArrayOne(left, right, opFloatCmpInt)
  1201  	})
  1202  }
  1203  
  1204  func floatarrayNotIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1205  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1206  		return cmpArrayOne(left, right, opFloatCmpInt)
  1207  	})
  1208  }
  1209  
  1210  // string -- []T
  1211  
  1212  func stringCmpBoolarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1213  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1214  		return cmpArrayOne(right, left, opBoolCmpString)
  1215  	})
  1216  }
  1217  
  1218  func stringNotBoolarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1219  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1220  		return cmpArrayOne(right, left, opBoolCmpString)
  1221  	})
  1222  }
  1223  
  1224  func boolarrayCmpStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1225  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1226  		return cmpArrayOne(left, right, opBoolCmpString)
  1227  	})
  1228  }
  1229  
  1230  func boolarrayNotStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1231  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1232  		return cmpArrayOne(left, right, opBoolCmpString)
  1233  	})
  1234  }
  1235  
  1236  func stringCmpIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1237  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1238  		return cmpArrayOne(right, left, opIntCmpString)
  1239  	})
  1240  }
  1241  
  1242  func stringNotIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1243  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1244  		return cmpArrayOne(right, left, opIntCmpString)
  1245  	})
  1246  }
  1247  
  1248  func intarrayCmpStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1249  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1250  		return cmpArrayOne(left, right, opIntCmpString)
  1251  	})
  1252  }
  1253  
  1254  func intarrayNotStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1255  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1256  		return cmpArrayOne(left, right, opIntCmpString)
  1257  	})
  1258  }
  1259  
  1260  func stringCmpFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1261  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1262  		return cmpArrayOne(right, left, opFloatCmpString)
  1263  	})
  1264  }
  1265  
  1266  func stringNotFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1267  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1268  		return cmpArrayOne(right, left, opFloatCmpString)
  1269  	})
  1270  }
  1271  
  1272  func floatarrayCmpStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1273  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1274  		return cmpArrayOne(left, right, opFloatCmpString)
  1275  	})
  1276  }
  1277  
  1278  func floatarrayNotStringV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1279  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1280  		return cmpArrayOne(left, right, opFloatCmpString)
  1281  	})
  1282  }
  1283  
  1284  // bool -- []string
  1285  
  1286  func boolCmpStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1287  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1288  		return cmpArrayOne(right, left, opStringCmpBool)
  1289  	})
  1290  }
  1291  
  1292  func boolNotStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1293  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1294  		return cmpArrayOne(right, left, opStringCmpBool)
  1295  	})
  1296  }
  1297  
  1298  func stringarrayCmpBoolV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1299  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1300  		return cmpArrayOne(left, right, opStringCmpBool)
  1301  	})
  1302  }
  1303  
  1304  func stringarrayNotBoolV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1305  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1306  		return cmpArrayOne(left, right, opStringCmpBool)
  1307  	})
  1308  }
  1309  
  1310  // int -- []string
  1311  
  1312  func intCmpStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1313  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1314  		return cmpArrayOne(right, left, opStringCmpInt)
  1315  	})
  1316  }
  1317  
  1318  func intNotStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1319  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1320  		return cmpArrayOne(right, left, opStringCmpInt)
  1321  	})
  1322  }
  1323  
  1324  func stringarrayCmpIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1325  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1326  		return cmpArrayOne(left, right, opStringCmpInt)
  1327  	})
  1328  }
  1329  
  1330  func stringarrayNotIntV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1331  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1332  		return cmpArrayOne(left, right, opStringCmpInt)
  1333  	})
  1334  }
  1335  
  1336  // float -- []string
  1337  
  1338  func floatCmpStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1339  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1340  		return cmpArrayOne(right, left, opStringCmpFloat)
  1341  	})
  1342  }
  1343  
  1344  func floatNotStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1345  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1346  		return cmpArrayOne(right, left, opStringCmpFloat)
  1347  	})
  1348  }
  1349  
  1350  func stringarrayCmpFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1351  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1352  		return cmpArrayOne(left, right, opStringCmpFloat)
  1353  	})
  1354  }
  1355  
  1356  func stringarrayNotFloatV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1357  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1358  		return cmpArrayOne(left, right, opStringCmpFloat)
  1359  	})
  1360  }
  1361  
  1362  // regex -- []T
  1363  
  1364  func regexCmpStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1365  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1366  		return cmpArrayOne(right, left, opStringCmpRegex)
  1367  	})
  1368  }
  1369  
  1370  func regexNotStringarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1371  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1372  		return cmpArrayOne(right, left, opStringCmpRegex)
  1373  	})
  1374  }
  1375  
  1376  func stringarrayCmpRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1377  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1378  		return cmpArrayOne(left, right, opStringCmpRegex)
  1379  	})
  1380  }
  1381  
  1382  func stringarrayNotRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1383  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1384  		return cmpArrayOne(left, right, opStringCmpRegex)
  1385  	})
  1386  }
  1387  
  1388  func regexCmpIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1389  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1390  		return cmpArrayOne(right, left, opIntCmpRegex)
  1391  	})
  1392  }
  1393  
  1394  func regexNotIntarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1395  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1396  		return cmpArrayOne(right, left, opIntCmpRegex)
  1397  	})
  1398  }
  1399  
  1400  func intarrayCmpRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1401  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1402  		return cmpArrayOne(left, right, opIntCmpRegex)
  1403  	})
  1404  }
  1405  
  1406  func intarrayNotRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1407  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1408  		return cmpArrayOne(left, right, opIntCmpRegex)
  1409  	})
  1410  }
  1411  
  1412  func regexCmpFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1413  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1414  		return cmpArrayOne(right, left, opFloatCmpRegex)
  1415  	})
  1416  }
  1417  
  1418  func regexNotFloatarrayV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1419  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1420  		return cmpArrayOne(right, left, opFloatCmpRegex)
  1421  	})
  1422  }
  1423  
  1424  func floatarrayCmpRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1425  	return rawboolOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1426  		return cmpArrayOne(left, right, opFloatCmpRegex)
  1427  	})
  1428  }
  1429  
  1430  func floatarrayNotRegexV2(e *blockExecutor, bind *RawData, chunk *Chunk, ref uint64) (*RawData, uint64, error) {
  1431  	return rawboolNotOpV2(e, bind, chunk, ref, func(left *RawData, right *RawData) bool {
  1432  		return cmpArrayOne(left, right, opFloatCmpRegex)
  1433  	})
  1434  }