github.com/matrixorigin/matrixone@v1.2.0/pkg/testutil/util_function.go (about)

     1  // Copyright 2021 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package testutil
    16  
    17  import (
    18  	"fmt"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/common/assertx"
    21  	"github.com/matrixorigin/matrixone/pkg/common/mpool"
    22  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    25  	"github.com/matrixorigin/matrixone/pkg/vectorize/moarray"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    27  )
    28  
    29  type fEvalFn func(parameters []*vector.Vector, result vector.FunctionResultWrapper, proc *process.Process, length int) error
    30  
    31  type FunctionTestCase struct {
    32  	proc       *process.Process
    33  	parameters []*vector.Vector
    34  	result     vector.FunctionResultWrapper
    35  	expected   FunctionTestResult
    36  	fn         fEvalFn
    37  	fnLength   int
    38  }
    39  
    40  // FunctionTestInput
    41  // the values should fit to typ.
    42  // for example:
    43  // if typ is int64, the values should be []int64
    44  // if your typ is string type (varchar or others), the values should be []string.
    45  type FunctionTestInput struct {
    46  	typ      types.Type
    47  	values   any
    48  	nullList []bool
    49  	isConst  bool
    50  }
    51  
    52  // FunctionTestResult
    53  // the wanted should fit to typ.
    54  // for example:
    55  // if typ is int64, the wanted should be []int64
    56  // if your typ is string type (varchar or others), the wanted should be []string.
    57  type FunctionTestResult struct {
    58  	typ      types.Type
    59  	wantErr  bool
    60  	wanted   any
    61  	nullList []bool
    62  }
    63  
    64  func NewFunctionTestInput(typ types.Type, values any, nullList []bool) FunctionTestInput {
    65  	return FunctionTestInput{
    66  		typ:      typ,
    67  		values:   values,
    68  		nullList: nullList,
    69  	}
    70  }
    71  
    72  func NewFunctionTestConstInput(typ types.Type, values any, nullList []bool) FunctionTestInput {
    73  	return FunctionTestInput{
    74  		typ:      typ,
    75  		values:   values,
    76  		nullList: nullList,
    77  		isConst:  true,
    78  	}
    79  }
    80  
    81  func NewFunctionTestResult(typ types.Type, wantErr bool, wanted any, nullList []bool) FunctionTestResult {
    82  	return FunctionTestResult{
    83  		typ:      typ,
    84  		wantErr:  wantErr,
    85  		wanted:   wanted,
    86  		nullList: nullList,
    87  	}
    88  }
    89  
    90  // NewFunctionTestCase generate a testcase for built-in function F.
    91  // fn is the evaluate method of F.
    92  func NewFunctionTestCase(
    93  	proc *process.Process,
    94  	inputs []FunctionTestInput,
    95  	wanted FunctionTestResult,
    96  	fn fEvalFn) FunctionTestCase {
    97  	f := FunctionTestCase{proc: proc}
    98  	mp := proc.Mp()
    99  	// allocate vector for function parameters
   100  	f.parameters = make([]*vector.Vector, len(inputs))
   101  	for i := range f.parameters {
   102  		typ := inputs[i].typ
   103  		// generate the nulls.
   104  		var nsp *nulls.Nulls = nil
   105  		if len(inputs[i].nullList) != 0 {
   106  			nsp = nulls.NewWithSize(len(inputs[i].nullList))
   107  			for j, b := range inputs[i].nullList {
   108  				if b {
   109  					nsp.Set(uint64(j))
   110  				}
   111  			}
   112  		}
   113  		// new the vector.
   114  		f.parameters[i] = newVectorByType(proc.Mp(), typ, inputs[i].values, nsp)
   115  		if inputs[i].isConst {
   116  			f.parameters[i].SetClass(vector.CONSTANT)
   117  		}
   118  	}
   119  	// new the result
   120  	f.result = vector.NewFunctionResultWrapper(proc.GetVector, proc.PutVector, wanted.typ, mp)
   121  	if len(f.parameters) == 0 {
   122  		f.fnLength = 1
   123  	} else {
   124  		f.fnLength = f.parameters[0].Length()
   125  	}
   126  	f.expected = wanted
   127  	f.fn = fn
   128  	return f
   129  }
   130  
   131  func (fc *FunctionTestCase) GetResultVectorDirectly() *vector.Vector {
   132  	return fc.result.GetResultVector()
   133  }
   134  
   135  // Run will run the function case and do the correctness check for result.
   136  func (fc *FunctionTestCase) Run() (succeed bool, errInfo string) {
   137  	err := fc.result.PreExtendAndReset(fc.fnLength)
   138  	if err != nil {
   139  		panic(err)
   140  	}
   141  
   142  	err = fc.fn(fc.parameters, fc.result, fc.proc, fc.fnLength)
   143  	if err != nil {
   144  		if fc.expected.wantErr {
   145  			return true, ""
   146  		}
   147  		return false, fmt.Sprintf("expected to run success, but get an error that '%s'",
   148  			err.Error())
   149  	}
   150  	if fc.expected.wantErr {
   151  		return false, "expected to run failed, but run succeed with no error"
   152  	}
   153  	v := fc.result.GetResultVector()
   154  	// check the length
   155  	if fc.fnLength != v.Length() {
   156  		return false, fmt.Sprintf("expected %d rows but get %d rows", fc.fnLength, v.Length())
   157  	}
   158  	// check type (it's stupid, haha
   159  	if v.GetType().Oid != fc.expected.typ.Oid {
   160  		return false, fmt.Sprintf("expected result type %s but get type %s", fc.expected.typ,
   161  			v.GetType())
   162  	}
   163  	// generate the expected nsp
   164  	var expectedNsp *nulls.Nulls = nil
   165  	if fc.expected.nullList != nil {
   166  		expectedNsp = nulls.NewWithSize(len(fc.expected.nullList))
   167  		for i, b := range fc.expected.nullList {
   168  			if b {
   169  				expectedNsp.Add(uint64(i))
   170  			}
   171  		}
   172  	}
   173  	// check the value
   174  	col := fc.expected.wanted
   175  	vExpected := newVectorByType(fc.proc.Mp(), fc.expected.typ, col, expectedNsp)
   176  	var i uint64
   177  	switch v.GetType().Oid {
   178  	case types.T_bool:
   179  		r := vector.GenerateFunctionFixedTypeParameter[bool](v)
   180  		s := vector.GenerateFunctionFixedTypeParameter[bool](vExpected)
   181  		for i = 0; i < uint64(fc.fnLength); i++ {
   182  			want, null1 := s.GetValue(i)
   183  			get, null2 := r.GetValue(i)
   184  			if null1 {
   185  				if null2 {
   186  					continue
   187  				} else {
   188  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   189  				}
   190  			}
   191  			if null2 {
   192  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   193  			}
   194  			if null2 {
   195  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   196  			}
   197  			if want != get {
   198  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   199  					i+1, want, get)
   200  			}
   201  		}
   202  	case types.T_bit:
   203  		r := vector.GenerateFunctionFixedTypeParameter[uint64](v)
   204  		s := vector.GenerateFunctionFixedTypeParameter[uint64](vExpected)
   205  		for i = 0; i < uint64(fc.fnLength); i++ {
   206  			want, null1 := s.GetValue(i)
   207  			get, null2 := r.GetValue(i)
   208  			if null1 {
   209  				if null2 {
   210  					continue
   211  				} else {
   212  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   213  				}
   214  			}
   215  			if null2 {
   216  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   217  			}
   218  			if want != get {
   219  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   220  					i+1, want, get)
   221  			}
   222  		}
   223  	case types.T_int8:
   224  		r := vector.GenerateFunctionFixedTypeParameter[int8](v)
   225  		s := vector.GenerateFunctionFixedTypeParameter[int8](vExpected)
   226  		for i = 0; i < uint64(fc.fnLength); i++ {
   227  			want, null1 := s.GetValue(i)
   228  			get, null2 := r.GetValue(i)
   229  			if null1 {
   230  				if null2 {
   231  					continue
   232  				} else {
   233  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   234  				}
   235  			}
   236  			if null2 {
   237  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   238  			}
   239  			if want != get {
   240  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   241  					i+1, want, get)
   242  			}
   243  		}
   244  	case types.T_int16:
   245  		r := vector.GenerateFunctionFixedTypeParameter[int16](v)
   246  		s := vector.GenerateFunctionFixedTypeParameter[int16](vExpected)
   247  		for i = 0; i < uint64(fc.fnLength); i++ {
   248  			want, null1 := s.GetValue(i)
   249  			get, null2 := r.GetValue(i)
   250  			if null1 {
   251  				if null2 {
   252  					continue
   253  				} else {
   254  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   255  				}
   256  			}
   257  			if null2 {
   258  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   259  			}
   260  			if want != get {
   261  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   262  					i+1, want, get)
   263  			}
   264  		}
   265  	case types.T_int32:
   266  		r := vector.GenerateFunctionFixedTypeParameter[int32](v)
   267  		s := vector.GenerateFunctionFixedTypeParameter[int32](vExpected)
   268  		for i = 0; i < uint64(fc.fnLength); i++ {
   269  			want, null1 := s.GetValue(i)
   270  			get, null2 := r.GetValue(i)
   271  			if null1 {
   272  				if null2 {
   273  					continue
   274  				} else {
   275  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   276  				}
   277  			}
   278  			if null2 {
   279  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   280  			}
   281  			if want != get {
   282  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   283  					i+1, want, get)
   284  			}
   285  		}
   286  	case types.T_int64:
   287  		r := vector.GenerateFunctionFixedTypeParameter[int64](v)
   288  		s := vector.GenerateFunctionFixedTypeParameter[int64](vExpected)
   289  		for i = 0; i < uint64(fc.fnLength); i++ {
   290  			want, null1 := s.GetValue(i)
   291  			get, null2 := r.GetValue(i)
   292  			if null1 {
   293  				if null2 {
   294  					continue
   295  				} else {
   296  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   297  				}
   298  			}
   299  			if null2 {
   300  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   301  			}
   302  			if want != get {
   303  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   304  					i+1, want, get)
   305  			}
   306  		}
   307  	case types.T_uint8:
   308  		r := vector.GenerateFunctionFixedTypeParameter[uint8](v)
   309  		s := vector.GenerateFunctionFixedTypeParameter[uint8](vExpected)
   310  		for i = 0; i < uint64(fc.fnLength); i++ {
   311  			want, null1 := s.GetValue(i)
   312  			get, null2 := r.GetValue(i)
   313  			if null1 {
   314  				if null2 {
   315  					continue
   316  				} else {
   317  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   318  				}
   319  			}
   320  			if null2 {
   321  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   322  			}
   323  			if want != get {
   324  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   325  					i+1, want, get)
   326  			}
   327  		}
   328  	case types.T_uint16:
   329  		r := vector.GenerateFunctionFixedTypeParameter[uint16](v)
   330  		s := vector.GenerateFunctionFixedTypeParameter[uint16](vExpected)
   331  		for i = 0; i < uint64(fc.fnLength); i++ {
   332  			want, null1 := s.GetValue(i)
   333  			get, null2 := r.GetValue(i)
   334  			if null1 {
   335  				if null2 {
   336  					continue
   337  				} else {
   338  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   339  				}
   340  			}
   341  			if null2 {
   342  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   343  			}
   344  			if want != get {
   345  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   346  					i+1, want, get)
   347  			}
   348  		}
   349  	case types.T_uint32:
   350  		r := vector.GenerateFunctionFixedTypeParameter[uint32](v)
   351  		s := vector.GenerateFunctionFixedTypeParameter[uint32](vExpected)
   352  		for i = 0; i < uint64(fc.fnLength); i++ {
   353  			want, null1 := s.GetValue(i)
   354  			get, null2 := r.GetValue(i)
   355  			if null1 {
   356  				if null2 {
   357  					continue
   358  				} else {
   359  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   360  				}
   361  			}
   362  			if null2 {
   363  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   364  			}
   365  			if want != get {
   366  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   367  					i+1, want, get)
   368  			}
   369  		}
   370  	case types.T_uint64:
   371  		r := vector.GenerateFunctionFixedTypeParameter[uint64](v)
   372  		s := vector.GenerateFunctionFixedTypeParameter[uint64](vExpected)
   373  		for i = 0; i < uint64(fc.fnLength); i++ {
   374  			want, null1 := s.GetValue(i)
   375  			get, null2 := r.GetValue(i)
   376  			if null1 {
   377  				if null2 {
   378  					continue
   379  				} else {
   380  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   381  				}
   382  			}
   383  			if null2 {
   384  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   385  			}
   386  			if want != get {
   387  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   388  					i+1, want, get)
   389  			}
   390  		}
   391  	case types.T_float32:
   392  		r := vector.GenerateFunctionFixedTypeParameter[float32](v)
   393  		s := vector.GenerateFunctionFixedTypeParameter[float32](vExpected)
   394  		for i = 0; i < uint64(fc.fnLength); i++ {
   395  			want, null1 := s.GetValue(i)
   396  			get, null2 := r.GetValue(i)
   397  			if null1 {
   398  				if null2 {
   399  					continue
   400  				} else {
   401  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   402  				}
   403  			}
   404  			if null2 {
   405  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   406  			}
   407  			if want != get {
   408  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   409  					i+1, want, get)
   410  			}
   411  		}
   412  	case types.T_float64:
   413  		r := vector.GenerateFunctionFixedTypeParameter[float64](v)
   414  		s := vector.GenerateFunctionFixedTypeParameter[float64](vExpected)
   415  		for i = 0; i < uint64(fc.fnLength); i++ {
   416  			want, null1 := s.GetValue(i)
   417  			get, null2 := r.GetValue(i)
   418  			if null1 {
   419  				if null2 {
   420  					continue
   421  				} else {
   422  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   423  				}
   424  			}
   425  			if null2 {
   426  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   427  			}
   428  			if !assertx.InEpsilonF64(want, get) {
   429  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   430  					i+1, want, get)
   431  			}
   432  		}
   433  	case types.T_decimal64:
   434  		r := vector.GenerateFunctionFixedTypeParameter[types.Decimal64](v)
   435  		s := vector.GenerateFunctionFixedTypeParameter[types.Decimal64](vExpected)
   436  		for i = 0; i < uint64(fc.fnLength); i++ {
   437  			want, null1 := s.GetValue(i)
   438  			get, null2 := r.GetValue(i)
   439  			if null1 {
   440  				if null2 {
   441  					continue
   442  				} else {
   443  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   444  				}
   445  			}
   446  			if null2 {
   447  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   448  			}
   449  			if want != get {
   450  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   451  					i+1, want, get)
   452  			}
   453  		}
   454  	case types.T_decimal128:
   455  		r := vector.GenerateFunctionFixedTypeParameter[types.Decimal128](v)
   456  		s := vector.GenerateFunctionFixedTypeParameter[types.Decimal128](vExpected)
   457  		for i = 0; i < uint64(fc.fnLength); i++ {
   458  			want, null1 := s.GetValue(i)
   459  			get, null2 := r.GetValue(i)
   460  			if null1 {
   461  				if null2 {
   462  					continue
   463  				} else {
   464  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   465  				}
   466  			}
   467  			if null2 {
   468  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   469  			}
   470  			if want != get {
   471  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   472  					i+1, want, get)
   473  			}
   474  		}
   475  	case types.T_date:
   476  		r := vector.GenerateFunctionFixedTypeParameter[types.Date](v)
   477  		s := vector.GenerateFunctionFixedTypeParameter[types.Date](vExpected)
   478  		for i = 0; i < uint64(fc.fnLength); i++ {
   479  			want, null1 := s.GetValue(i)
   480  			get, null2 := r.GetValue(i)
   481  			if null1 {
   482  				if null2 {
   483  					continue
   484  				} else {
   485  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   486  				}
   487  			}
   488  			if null2 {
   489  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   490  			}
   491  			if want != get {
   492  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   493  					i+1, want, get)
   494  			}
   495  		}
   496  	case types.T_datetime:
   497  		r := vector.GenerateFunctionFixedTypeParameter[types.Datetime](v)
   498  		s := vector.GenerateFunctionFixedTypeParameter[types.Datetime](vExpected)
   499  		for i = 0; i < uint64(fc.fnLength); i++ {
   500  			want, null1 := s.GetValue(i)
   501  			get, null2 := r.GetValue(i)
   502  			if null1 {
   503  				if null2 {
   504  					continue
   505  				} else {
   506  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   507  				}
   508  			}
   509  			if null2 {
   510  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   511  			}
   512  			if want != get {
   513  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   514  					i+1, want, get)
   515  			}
   516  		}
   517  	case types.T_time:
   518  		r := vector.GenerateFunctionFixedTypeParameter[types.Time](v)
   519  		s := vector.GenerateFunctionFixedTypeParameter[types.Time](vExpected)
   520  		for i = 0; i < uint64(fc.fnLength); i++ {
   521  			want, null1 := s.GetValue(i)
   522  			get, null2 := r.GetValue(i)
   523  			if null1 {
   524  				if null2 {
   525  					continue
   526  				} else {
   527  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   528  				}
   529  			}
   530  			if null2 {
   531  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   532  			}
   533  			if want != get {
   534  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   535  					i+1, want, get)
   536  			}
   537  		}
   538  	case types.T_timestamp:
   539  		r := vector.GenerateFunctionFixedTypeParameter[types.Timestamp](v)
   540  		s := vector.GenerateFunctionFixedTypeParameter[types.Timestamp](vExpected)
   541  		for i = 0; i < uint64(fc.fnLength); i++ {
   542  			want, null1 := s.GetValue(i)
   543  			get, null2 := r.GetValue(i)
   544  			if null1 {
   545  				if null2 {
   546  					continue
   547  				} else {
   548  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   549  				}
   550  			}
   551  			if null2 {
   552  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   553  			}
   554  			if want != get {
   555  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   556  					i+1, want, get)
   557  			}
   558  		}
   559  	case types.T_enum:
   560  		r := vector.GenerateFunctionFixedTypeParameter[types.Enum](v)
   561  		s := vector.GenerateFunctionFixedTypeParameter[types.Enum](vExpected)
   562  		for i = 0; i < uint64(fc.fnLength); i++ {
   563  			want, null1 := s.GetValue(i)
   564  			get, null2 := r.GetValue(i)
   565  			if null1 {
   566  				if null2 {
   567  					continue
   568  				} else {
   569  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   570  				}
   571  			}
   572  			if null2 {
   573  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   574  			}
   575  			if want != get {
   576  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   577  					i+1, want, get)
   578  			}
   579  		}
   580  	case types.T_char, types.T_varchar,
   581  		types.T_binary, types.T_varbinary, types.T_blob, types.T_text:
   582  		r := vector.GenerateFunctionStrParameter(v)
   583  		s := vector.GenerateFunctionStrParameter(vExpected)
   584  		for i = 0; i < uint64(fc.fnLength); i++ {
   585  			want, null1 := s.GetStrValue(i)
   586  			get, null2 := r.GetStrValue(i)
   587  			if null1 {
   588  				if null2 {
   589  					continue
   590  				} else {
   591  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   592  				}
   593  			}
   594  			if null2 {
   595  				return false, fmt.Sprintf("the %dth row expected %s, but get NULL", i+1, string(want))
   596  			}
   597  			if string(want) != string(get) {
   598  				return false, fmt.Sprintf("the %dth row expected %s, but get %s",
   599  					i+1, string(want), string(get))
   600  			}
   601  		}
   602  
   603  	case types.T_array_float32:
   604  		r := vector.GenerateFunctionStrParameter(v)
   605  		s := vector.GenerateFunctionStrParameter(vExpected)
   606  		for i = 0; i < uint64(fc.fnLength); i++ {
   607  			want, null1 := s.GetStrValue(i)
   608  			get, null2 := r.GetStrValue(i)
   609  			if null1 {
   610  				if null2 {
   611  					continue
   612  				} else {
   613  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   614  				}
   615  			}
   616  			if null2 {
   617  				return false, fmt.Sprintf("the %dth row expected %s, but get NULL", i+1, string(want))
   618  			}
   619  			if moarray.Compare[float32](types.BytesToArray[float32](want), types.BytesToArray[float32](get)) != 0 {
   620  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   621  					i+1, types.BytesToArray[float32](want), types.BytesToArray[float32](get))
   622  			}
   623  		}
   624  	case types.T_array_float64:
   625  		r := vector.GenerateFunctionStrParameter(v)
   626  		s := vector.GenerateFunctionStrParameter(vExpected)
   627  		for i = 0; i < uint64(fc.fnLength); i++ {
   628  			want, null1 := s.GetStrValue(i)
   629  			get, null2 := r.GetStrValue(i)
   630  			if null1 {
   631  				if null2 {
   632  					continue
   633  				} else {
   634  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   635  				}
   636  			}
   637  			if null2 {
   638  				return false, fmt.Sprintf("the %dth row expected %s, but get NULL", i+1, string(want))
   639  			}
   640  			if !assertx.InEpsilonF64Slice(types.BytesToArray[float64](want), types.BytesToArray[float64](get)) {
   641  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   642  					i+1, types.BytesToArray[float64](want), types.BytesToArray[float64](get))
   643  			}
   644  		}
   645  	case types.T_uuid:
   646  		r := vector.GenerateFunctionFixedTypeParameter[types.Uuid](v)
   647  		s := vector.GenerateFunctionFixedTypeParameter[types.Uuid](vExpected)
   648  		for i = 0; i < uint64(fc.fnLength); i++ {
   649  			want, null1 := s.GetValue(i)
   650  			get, null2 := r.GetValue(i)
   651  			if null1 {
   652  				if null2 {
   653  					continue
   654  				} else {
   655  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   656  				}
   657  			}
   658  			if null2 {
   659  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   660  			}
   661  			if want != get {
   662  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   663  					i+1, want, get)
   664  			}
   665  		}
   666  	case types.T_TS:
   667  		r := vector.GenerateFunctionFixedTypeParameter[types.TS](v)
   668  		s := vector.GenerateFunctionFixedTypeParameter[types.TS](vExpected)
   669  		for i = 0; i < uint64(fc.fnLength); i++ {
   670  			want, null1 := s.GetValue(i)
   671  			get, null2 := r.GetValue(i)
   672  			if null1 {
   673  				if null2 {
   674  					continue
   675  				} else {
   676  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   677  				}
   678  			}
   679  			if null2 {
   680  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   681  			}
   682  			if want != get {
   683  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   684  					i+1, want, get)
   685  			}
   686  		}
   687  	case types.T_Rowid:
   688  		r := vector.GenerateFunctionFixedTypeParameter[types.Rowid](v)
   689  		s := vector.GenerateFunctionFixedTypeParameter[types.Rowid](vExpected)
   690  		for i = 0; i < uint64(fc.fnLength); i++ {
   691  			want, null1 := s.GetValue(i)
   692  			get, null2 := r.GetValue(i)
   693  			if null1 {
   694  				if null2 {
   695  					continue
   696  				} else {
   697  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   698  				}
   699  			}
   700  			if null2 {
   701  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   702  			}
   703  			if want != get {
   704  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   705  					i+1, want, get)
   706  			}
   707  		}
   708  	case types.T_Blockid:
   709  		r := vector.GenerateFunctionFixedTypeParameter[types.Blockid](v)
   710  		s := vector.GenerateFunctionFixedTypeParameter[types.Blockid](vExpected)
   711  		for i = 0; i < uint64(fc.fnLength); i++ {
   712  			want, null1 := s.GetValue(i)
   713  			get, null2 := r.GetValue(i)
   714  			if null1 {
   715  				if null2 {
   716  					continue
   717  				} else {
   718  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   719  				}
   720  			}
   721  			if null2 {
   722  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   723  			}
   724  			if want != get {
   725  				return false, fmt.Sprintf("the %dth row expected %v, but get %v",
   726  					i+1, want, get)
   727  			}
   728  		}
   729  	case types.T_json:
   730  		r := vector.GenerateFunctionStrParameter(v)
   731  		s := vector.GenerateFunctionStrParameter(vExpected)
   732  		for i = 0; i < uint64(fc.fnLength); i++ {
   733  			want, null1 := s.GetStrValue(i)
   734  			get, null2 := r.GetStrValue(i)
   735  			if null1 {
   736  				if null2 {
   737  					continue
   738  				} else {
   739  					return false, fmt.Sprintf("the %dth row expected NULL, but get not null", i+1)
   740  				}
   741  			}
   742  			if null2 {
   743  				return false, fmt.Sprintf("the %dth row expected %v, but get NULL", i+1, want)
   744  			}
   745  			if string(want) != string(get) {
   746  				return false, fmt.Sprintf("the %dth row expected %s, but get %s",
   747  					i+1, string(want), string(get))
   748  			}
   749  		}
   750  	default:
   751  		panic(fmt.Sprintf("unsupported result type %s for function ut framework", v.GetType()))
   752  	}
   753  	return true, ""
   754  }
   755  
   756  // DebugRun will not run the compare logic for function result but return the result vector directly.
   757  func (fc *FunctionTestCase) DebugRun() (*vector.Vector, error) {
   758  	err := fc.fn(fc.parameters, fc.result, fc.proc, fc.fnLength)
   759  	return fc.result.GetResultVector(), err
   760  }
   761  
   762  // BenchMarkRun will run the function case N times without correctness check for result.
   763  func (fc *FunctionTestCase) BenchMarkRun() error {
   764  	num := 100000
   765  	for num > 0 {
   766  		num--
   767  		err := fc.fn(fc.parameters, fc.result, fc.proc, fc.fnLength)
   768  		// XXX maybe free is unnecessary.
   769  		typ := fc.result.GetResultVector().GetType()
   770  		fc.result.GetResultVector().Reset(*typ)
   771  		if err != nil {
   772  			return err
   773  		}
   774  	}
   775  	return nil
   776  }
   777  
   778  func newVectorByType(mp *mpool.MPool, typ types.Type, val any, nsp *nulls.Nulls) *vector.Vector {
   779  	vec := vector.NewVec(typ)
   780  	switch typ.Oid {
   781  	case types.T_bool:
   782  		values := val.([]bool)
   783  		vector.AppendFixedList(vec, values, nil, mp)
   784  	case types.T_bit:
   785  		values := val.([]uint64)
   786  		vector.AppendFixedList(vec, values, nil, mp)
   787  	case types.T_int8:
   788  		values := val.([]int8)
   789  		vector.AppendFixedList(vec, values, nil, mp)
   790  	case types.T_int16:
   791  		values := val.([]int16)
   792  		vector.AppendFixedList(vec, values, nil, mp)
   793  	case types.T_int32:
   794  		values := val.([]int32)
   795  		vector.AppendFixedList(vec, values, nil, mp)
   796  	case types.T_int64:
   797  		values := val.([]int64)
   798  		vector.AppendFixedList(vec, values, nil, mp)
   799  	case types.T_uint8:
   800  		values := val.([]uint8)
   801  		vector.AppendFixedList(vec, values, nil, mp)
   802  	case types.T_uint16:
   803  		values := val.([]uint16)
   804  		vector.AppendFixedList(vec, values, nil, mp)
   805  	case types.T_uint32:
   806  		values := val.([]uint32)
   807  		vector.AppendFixedList(vec, values, nil, mp)
   808  	case types.T_uint64:
   809  		values := val.([]uint64)
   810  		vector.AppendFixedList(vec, values, nil, mp)
   811  	case types.T_float32:
   812  		values := val.([]float32)
   813  		vector.AppendFixedList(vec, values, nil, mp)
   814  	case types.T_float64:
   815  		values := val.([]float64)
   816  		vector.AppendFixedList(vec, values, nil, mp)
   817  	case types.T_decimal64:
   818  		values := val.([]types.Decimal64)
   819  		vector.AppendFixedList(vec, values, nil, mp)
   820  	case types.T_decimal128:
   821  		values := val.([]types.Decimal128)
   822  		vector.AppendFixedList(vec, values, nil, mp)
   823  	case types.T_date:
   824  		values := val.([]types.Date)
   825  		vector.AppendFixedList(vec, values, nil, mp)
   826  	case types.T_datetime:
   827  		values := val.([]types.Datetime)
   828  		vector.AppendFixedList(vec, values, nil, mp)
   829  	case types.T_time:
   830  		values := val.([]types.Time)
   831  		vector.AppendFixedList(vec, values, nil, mp)
   832  	case types.T_timestamp:
   833  		values := val.([]types.Timestamp)
   834  		vector.AppendFixedList(vec, values, nil, mp)
   835  	case types.T_char, types.T_varchar, types.T_binary, types.T_varbinary, types.T_blob, types.T_text:
   836  		values := val.([]string)
   837  		vector.AppendStringList(vec, values, nil, mp)
   838  	case types.T_array_float32:
   839  		values := val.([][]float32)
   840  		vector.AppendArrayList[float32](vec, values, nil, mp)
   841  	case types.T_array_float64:
   842  		values := val.([][]float64)
   843  		vector.AppendArrayList[float64](vec, values, nil, mp)
   844  	case types.T_uuid:
   845  		values := val.([]types.Uuid)
   846  		vector.AppendFixedList(vec, values, nil, mp)
   847  	case types.T_TS:
   848  		values := val.([]types.TS)
   849  		vector.AppendFixedList(vec, values, nil, mp)
   850  	case types.T_Rowid:
   851  		values := val.([]types.Rowid)
   852  		vector.AppendFixedList(vec, values, nil, mp)
   853  	case types.T_Blockid:
   854  		values := val.([]types.Blockid)
   855  		vector.AppendFixedList(vec, values, nil, mp)
   856  	case types.T_json:
   857  		values := val.([]string)
   858  		vector.AppendStringList(vec, values, nil, mp)
   859  	case types.T_enum:
   860  		values := val.([]types.Enum)
   861  		vector.AppendFixedList(vec, values, nil, mp)
   862  	default:
   863  		panic(fmt.Sprintf("function test framework do not support typ %s", typ))
   864  	}
   865  	vec.SetNulls(nsp)
   866  	return vec
   867  }