github.com/apache/arrow/go/v14@v14.0.2/arrow/compute/exec/kernel_test.go (about)

     1  // Licensed to the Apache Software Foundation (ASF) under one
     2  // or more contributor license agreements.  See the NOTICE file
     3  // distributed with this work for additional information
     4  // regarding copyright ownership.  The ASF licenses this file
     5  // to you under the Apache License, Version 2.0 (the
     6  // "License"); you may not use this file except in compliance
     7  // with the License.  You may obtain a copy of the License at
     8  //
     9  // http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  
    17  //go:build go1.18
    18  
    19  package exec_test
    20  
    21  import (
    22  	"fmt"
    23  	"testing"
    24  
    25  	"github.com/apache/arrow/go/v14/arrow"
    26  	"github.com/apache/arrow/go/v14/arrow/array"
    27  	"github.com/apache/arrow/go/v14/arrow/compute"
    28  	"github.com/apache/arrow/go/v14/arrow/compute/exec"
    29  	"github.com/apache/arrow/go/v14/arrow/memory"
    30  	"github.com/apache/arrow/go/v14/arrow/scalar"
    31  	"github.com/stretchr/testify/assert"
    32  )
    33  
    34  func TestTypeMatcherSameTypeID(t *testing.T) {
    35  	matcher := exec.SameTypeID(arrow.DECIMAL128)
    36  	assert.True(t, matcher.Matches(&arrow.Decimal128Type{Precision: 12, Scale: 2}))
    37  	assert.False(t, matcher.Matches(arrow.PrimitiveTypes.Int8))
    38  
    39  	assert.Equal(t, "Type::DECIMAL128", matcher.String())
    40  
    41  	assert.True(t, matcher.Equals(matcher))
    42  	assert.True(t, matcher.Equals(exec.SameTypeID(arrow.DECIMAL)))
    43  	assert.False(t, matcher.Equals(exec.SameTypeID(arrow.TIMESTAMP)))
    44  	assert.False(t, matcher.Equals(exec.Time32TypeUnit(arrow.Microsecond)))
    45  }
    46  
    47  func TestTypeMatcherTimestampTypeUnit(t *testing.T) {
    48  	matcher := exec.TimestampTypeUnit(arrow.Millisecond)
    49  	matcher2 := exec.Time32TypeUnit(arrow.Millisecond)
    50  	matcher3 := exec.Time64TypeUnit(arrow.Microsecond)
    51  	matcher4 := exec.DurationTypeUnit(arrow.Microsecond)
    52  
    53  	assert.True(t, matcher.Matches(arrow.FixedWidthTypes.Timestamp_ms))
    54  	assert.True(t, matcher.Matches(&arrow.TimestampType{Unit: arrow.Millisecond, TimeZone: "utc"}))
    55  	assert.False(t, matcher.Matches(arrow.FixedWidthTypes.Timestamp_s))
    56  	assert.False(t, matcher.Matches(arrow.FixedWidthTypes.Time32ms))
    57  	assert.True(t, matcher2.Matches(arrow.FixedWidthTypes.Time32ms))
    58  
    59  	assert.True(t, matcher3.Matches(arrow.FixedWidthTypes.Time64us))
    60  	assert.False(t, matcher3.Matches(arrow.FixedWidthTypes.Time64ns))
    61  	assert.True(t, matcher4.Matches(arrow.FixedWidthTypes.Duration_us))
    62  	assert.False(t, matcher4.Matches(arrow.FixedWidthTypes.Duration_ms))
    63  
    64  	// check String() representation
    65  	assert.Equal(t, "timestamp(s)", exec.TimestampTypeUnit(arrow.Second).String())
    66  	assert.Equal(t, "timestamp(ms)", exec.TimestampTypeUnit(arrow.Millisecond).String())
    67  	assert.Equal(t, "timestamp(us)", exec.TimestampTypeUnit(arrow.Microsecond).String())
    68  	assert.Equal(t, "timestamp(ns)", exec.TimestampTypeUnit(arrow.Nanosecond).String())
    69  
    70  	// equals implementation
    71  	assert.True(t, matcher.Equals(matcher))
    72  	assert.True(t, matcher.Equals(exec.TimestampTypeUnit(arrow.Millisecond)))
    73  	assert.False(t, matcher.Equals(exec.TimestampTypeUnit(arrow.Microsecond)))
    74  	assert.False(t, matcher.Equals(exec.Time32TypeUnit(arrow.Millisecond)))
    75  	assert.False(t, matcher3.Equals(matcher2))
    76  	assert.False(t, matcher4.Equals(matcher3))
    77  	assert.True(t, matcher4.Equals(exec.DurationTypeUnit(arrow.Microsecond)))
    78  	assert.False(t, matcher.Equals(exec.SameTypeID(arrow.TIMESTAMP)))
    79  }
    80  
    81  func TestIntegerMatcher(t *testing.T) {
    82  	match := exec.Integer()
    83  
    84  	assert.Equal(t, "integer", match.String())
    85  	assert.True(t, match.Matches(arrow.PrimitiveTypes.Int8))
    86  	assert.True(t, match.Matches(arrow.PrimitiveTypes.Uint64))
    87  	assert.True(t, match.Equals(exec.Integer()))
    88  	assert.False(t, match.Equals(exec.BinaryLike()))
    89  }
    90  
    91  func TestBinaryLikeMatcher(t *testing.T) {
    92  	match := exec.BinaryLike()
    93  
    94  	assert.Equal(t, "binary-like", match.String())
    95  	assert.True(t, match.Matches(arrow.BinaryTypes.String))
    96  	assert.True(t, match.Matches(arrow.BinaryTypes.Binary))
    97  	assert.False(t, match.Matches(arrow.BinaryTypes.LargeString))
    98  	assert.False(t, match.Matches(arrow.BinaryTypes.LargeBinary))
    99  	assert.False(t, match.Equals(exec.LargeBinaryLike()))
   100  	assert.True(t, match.Equals(exec.BinaryLike()))
   101  }
   102  
   103  func TestLargeBinaryLikeMatcher(t *testing.T) {
   104  	match := exec.LargeBinaryLike()
   105  
   106  	assert.Equal(t, "large-binary-like", match.String())
   107  	assert.False(t, match.Matches(arrow.BinaryTypes.String))
   108  	assert.False(t, match.Matches(arrow.BinaryTypes.Binary))
   109  	assert.True(t, match.Matches(arrow.BinaryTypes.LargeString))
   110  	assert.True(t, match.Matches(arrow.BinaryTypes.LargeBinary))
   111  	assert.True(t, match.Equals(exec.LargeBinaryLike()))
   112  	assert.False(t, match.Equals(exec.BinaryLike()))
   113  }
   114  
   115  func TestFixedSizeBinaryMatcher(t *testing.T) {
   116  	match := exec.FixedSizeBinaryLike()
   117  
   118  	assert.Equal(t, "fixed-size-binary-like", match.String())
   119  	assert.False(t, match.Matches(arrow.BinaryTypes.String))
   120  	assert.True(t, match.Matches(&arrow.Decimal128Type{Precision: 12, Scale: 5}))
   121  	assert.True(t, match.Matches(&arrow.Decimal256Type{Precision: 12, Scale: 10}))
   122  	assert.True(t, match.Matches(&arrow.FixedSizeBinaryType{}))
   123  	assert.False(t, match.Equals(exec.LargeBinaryLike()))
   124  	assert.True(t, match.Equals(exec.FixedSizeBinaryLike()))
   125  }
   126  
   127  func TestPrimitiveMatcher(t *testing.T) {
   128  	match := exec.Primitive()
   129  
   130  	assert.Equal(t, "primitive", match.String())
   131  	assert.True(t, match.Equals(exec.Primitive()))
   132  
   133  	types := []arrow.DataType{
   134  		arrow.FixedWidthTypes.Boolean,
   135  		arrow.PrimitiveTypes.Uint8,
   136  		arrow.PrimitiveTypes.Int8,
   137  		arrow.PrimitiveTypes.Uint16,
   138  		arrow.PrimitiveTypes.Int16,
   139  		arrow.PrimitiveTypes.Uint32,
   140  		arrow.PrimitiveTypes.Int32,
   141  		arrow.PrimitiveTypes.Uint64,
   142  		arrow.PrimitiveTypes.Int64,
   143  		arrow.FixedWidthTypes.Float16,
   144  		arrow.PrimitiveTypes.Float32,
   145  		arrow.PrimitiveTypes.Float64,
   146  		arrow.FixedWidthTypes.Date32,
   147  		arrow.FixedWidthTypes.Date64,
   148  		arrow.FixedWidthTypes.Time32ms,
   149  		arrow.FixedWidthTypes.Time64ns,
   150  		arrow.FixedWidthTypes.Timestamp_ms,
   151  		arrow.FixedWidthTypes.Duration_ms,
   152  		arrow.FixedWidthTypes.MonthInterval,
   153  		arrow.FixedWidthTypes.DayTimeInterval,
   154  		arrow.FixedWidthTypes.MonthDayNanoInterval,
   155  	}
   156  
   157  	for _, typ := range types {
   158  		assert.True(t, match.Matches(typ))
   159  	}
   160  
   161  	assert.False(t, match.Matches(arrow.Null))
   162  }
   163  
   164  func TestREEMatcher(t *testing.T) {
   165  	tests := []struct {
   166  		runEnds        exec.TypeMatcher
   167  		enc            exec.TypeMatcher
   168  		matchRunEnds   arrow.DataType
   169  		nomatchRunEnds arrow.DataType
   170  		matchEnc       arrow.DataType
   171  		nomatchEnc     arrow.DataType
   172  	}{
   173  		{exec.Integer(), exec.Integer(), arrow.PrimitiveTypes.Int16, arrow.FixedWidthTypes.Float16, arrow.PrimitiveTypes.Int8, arrow.BinaryTypes.String},
   174  		{exec.SameTypeID(arrow.INT32), exec.BinaryLike(), arrow.PrimitiveTypes.Int32, arrow.PrimitiveTypes.Int64, arrow.BinaryTypes.String, arrow.PrimitiveTypes.Int32},
   175  		{exec.SameTypeID(arrow.INT64), exec.SameTypeID(arrow.STRUCT), arrow.PrimitiveTypes.Int64, arrow.PrimitiveTypes.Int32, arrow.StructOf(arrow.Field{Name: "a", Type: arrow.PrimitiveTypes.Int16}), arrow.PrimitiveTypes.Int8},
   176  	}
   177  
   178  	for _, tt := range tests {
   179  		t.Run(tt.enc.String(), func(t *testing.T) {
   180  			matcher := exec.RunEndEncoded(tt.runEnds, tt.enc)
   181  			assert.False(t, matcher.Matches(tt.matchEnc))
   182  			assert.True(t, matcher.Matches(arrow.RunEndEncodedOf(tt.matchRunEnds, tt.matchEnc)))
   183  			assert.False(t, matcher.Matches(arrow.RunEndEncodedOf(tt.matchRunEnds, tt.nomatchEnc)))
   184  			assert.False(t, matcher.Matches(arrow.RunEndEncodedOf(tt.nomatchRunEnds, tt.matchEnc)))
   185  			assert.False(t, matcher.Matches(arrow.RunEndEncodedOf(tt.nomatchRunEnds, tt.nomatchEnc)))
   186  
   187  			assert.Equal(t, "run_end_encoded(run_ends="+tt.runEnds.String()+", values="+tt.enc.String()+")", matcher.String())
   188  
   189  			assert.True(t, matcher.Equals(exec.RunEndEncoded(tt.runEnds, tt.enc)))
   190  			assert.False(t, matcher.Equals(exec.Primitive()))
   191  			assert.False(t, matcher.Equals(exec.RunEndEncoded(exec.SameTypeID(tt.nomatchRunEnds.ID()), exec.SameTypeID(tt.nomatchEnc.ID()))))
   192  			assert.False(t, matcher.Equals(exec.RunEndEncoded(exec.SameTypeID(tt.matchRunEnds.ID()), exec.SameTypeID(tt.nomatchEnc.ID()))))
   193  			assert.False(t, matcher.Equals(exec.RunEndEncoded(exec.SameTypeID(tt.nomatchRunEnds.ID()), exec.SameTypeID(tt.matchEnc.ID()))))
   194  		})
   195  	}
   196  }
   197  
   198  func TestInputTypeAnyType(t *testing.T) {
   199  	var ty exec.InputType
   200  	assert.Equal(t, exec.InputAny, ty.Kind)
   201  }
   202  
   203  func TestInputType(t *testing.T) {
   204  	ty1 := exec.NewExactInput(arrow.PrimitiveTypes.Int8)
   205  	assert.Equal(t, exec.InputExact, ty1.Kind)
   206  	assert.True(t, arrow.TypeEqual(arrow.PrimitiveTypes.Int8, ty1.Type))
   207  	assert.Equal(t, "int8", ty1.String())
   208  
   209  	ty2 := exec.NewIDInput(arrow.DECIMAL)
   210  	assert.Equal(t, exec.InputUseMatcher, ty2.Kind)
   211  	assert.Equal(t, "Type::DECIMAL128", ty2.String())
   212  	assert.True(t, ty2.Matcher.Matches(&arrow.Decimal128Type{Precision: 12, Scale: 2}))
   213  	assert.False(t, ty2.Matcher.Matches(arrow.PrimitiveTypes.Int16))
   214  
   215  	ty3 := exec.NewMatchedInput(exec.TimestampTypeUnit(arrow.Microsecond))
   216  	assert.Equal(t, "timestamp(us)", ty3.String())
   217  
   218  	var ty4 exec.InputType
   219  	assert.Equal(t, "any", ty4.String())
   220  	// InputAny matches anything
   221  	assert.True(t, ty4.Matches((arrow.DataType)(nil)))
   222  }
   223  
   224  func TestInputTypeEquals(t *testing.T) {
   225  	t1 := exec.NewExactInput(arrow.PrimitiveTypes.Int8)
   226  	t2 := exec.NewExactInput(arrow.PrimitiveTypes.Int8)
   227  	t3 := exec.NewExactInput(arrow.PrimitiveTypes.Int32)
   228  
   229  	t5 := exec.NewIDInput(arrow.DECIMAL)
   230  	t6 := exec.NewIDInput(arrow.DECIMAL)
   231  
   232  	assert.True(t, t1.Equals(&t2))
   233  	assert.False(t, t1.Equals(&t3))
   234  	assert.False(t, t1.Equals(&t5))
   235  	assert.True(t, t5.Equals(&t5))
   236  	assert.True(t, t5.Equals(&t6))
   237  
   238  	var ty exec.InputType
   239  	assert.True(t, ty.Equals(&exec.InputType{Kind: exec.InputAny}))
   240  
   241  	// for now, an ID matcher for arrow.INT32 and a ExactInput for
   242  	// arrow.PrimitiveTypes.Int32 are treated as being different.
   243  	// this could be made equivalent later if desireable
   244  
   245  	// check that field metadata is excluded from equality checks
   246  	t7 := exec.NewExactInput(arrow.ListOfField(
   247  		arrow.Field{Name: "item", Type: arrow.BinaryTypes.String,
   248  			Nullable: true, Metadata: arrow.NewMetadata([]string{"foo"}, []string{"bar"})}))
   249  	t8 := exec.NewExactInput(arrow.ListOf(arrow.BinaryTypes.String))
   250  	assert.True(t, t7.Equals(&t8))
   251  }
   252  
   253  func TestInputTypeHash(t *testing.T) {
   254  	var (
   255  		t0 exec.InputType
   256  		t1 = exec.NewExactInput(arrow.PrimitiveTypes.Int8)
   257  		t2 = exec.NewIDInput(arrow.DECIMAL)
   258  	)
   259  
   260  	// these checks try to determine first of all whether hash
   261  	// always returns the same value, and whether the elements
   262  	// of the type are all incorporated into the hash
   263  	assert.Equal(t, t0.Hash(), t0.Hash())
   264  	assert.Equal(t, t1.Hash(), t1.Hash())
   265  	assert.Equal(t, t2.Hash(), t2.Hash())
   266  	assert.NotEqual(t, t0.Hash(), t1.Hash())
   267  	assert.NotEqual(t, t0.Hash(), t2.Hash())
   268  	assert.NotEqual(t, t1.Hash(), t2.Hash())
   269  }
   270  
   271  func TestInputTypeMatches(t *testing.T) {
   272  	in1 := exec.NewExactInput(arrow.PrimitiveTypes.Int8)
   273  
   274  	assert.True(t, in1.Matches(arrow.PrimitiveTypes.Int8))
   275  	assert.False(t, in1.Matches(arrow.PrimitiveTypes.Int16))
   276  
   277  	in2 := exec.NewIDInput(arrow.DECIMAL)
   278  	assert.True(t, in2.Matches(&arrow.Decimal128Type{Precision: 12, Scale: 2}))
   279  
   280  	ty2 := &arrow.Decimal128Type{Precision: 12, Scale: 2}
   281  	ty3 := arrow.PrimitiveTypes.Float64
   282  
   283  	mem := memory.NewCheckedAllocator(memory.DefaultAllocator)
   284  	defer mem.AssertSize(t, 0)
   285  
   286  	arr2 := array.MakeArrayOfNull(mem, ty2, 1)
   287  	arr3 := array.MakeArrayOfNull(mem, ty3, 1)
   288  	defer arr2.Release()
   289  	defer arr3.Release()
   290  
   291  	scalar2, err := scalar.GetScalar(arr2, 0)
   292  	assert.NoError(t, err)
   293  
   294  	datumArr := compute.NewDatum(arr2)
   295  	defer datumArr.Release()
   296  	datumScalar := compute.NewDatum(scalar2)
   297  	defer datumScalar.Release()
   298  
   299  	assert.False(t, in2.Matches(ty3))
   300  	assert.False(t, in2.Matches(arr3.DataType()))
   301  }
   302  
   303  func TestOutputType(t *testing.T) {
   304  	ty1 := exec.NewOutputType(arrow.PrimitiveTypes.Int8)
   305  	assert.Equal(t, exec.ResolveFixed, ty1.Kind)
   306  	assert.True(t, arrow.TypeEqual(arrow.PrimitiveTypes.Int8, ty1.Type))
   307  
   308  	dummyResolver := func(_ *exec.KernelCtx, args []arrow.DataType) (arrow.DataType, error) {
   309  		return arrow.PrimitiveTypes.Int32, nil
   310  	}
   311  
   312  	ty2 := exec.NewComputedOutputType(dummyResolver)
   313  	assert.Equal(t, exec.ResolveComputed, ty2.Kind)
   314  
   315  	outType2, err := ty2.Resolve(nil, nil)
   316  	assert.NoError(t, err)
   317  	assert.Same(t, arrow.PrimitiveTypes.Int32, outType2)
   318  
   319  	ty3 := ty1
   320  	assert.Equal(t, exec.ResolveFixed, ty3.Kind)
   321  	assert.True(t, arrow.TypeEqual(ty1.Type, ty3.Type))
   322  
   323  	ty4 := ty2
   324  	assert.Equal(t, exec.ResolveComputed, ty4.Kind)
   325  	outType4, err := ty4.Resolve(nil, nil)
   326  	assert.NoError(t, err)
   327  	assert.Same(t, arrow.PrimitiveTypes.Int32, outType4)
   328  
   329  	assert.Equal(t, "int8", ty3.String())
   330  	assert.Equal(t, "computed", ty4.String())
   331  }
   332  
   333  func TestOutputTypeResolve(t *testing.T) {
   334  	ty1 := exec.NewOutputType(arrow.PrimitiveTypes.Int32)
   335  
   336  	result, err := ty1.Resolve(nil, nil)
   337  	assert.NoError(t, err)
   338  	assert.Same(t, arrow.PrimitiveTypes.Int32, result)
   339  
   340  	result, err = ty1.Resolve(nil, []arrow.DataType{arrow.PrimitiveTypes.Int8})
   341  	assert.NoError(t, err)
   342  	assert.Same(t, arrow.PrimitiveTypes.Int32, result)
   343  
   344  	result, err = ty1.Resolve(nil, []arrow.DataType{arrow.PrimitiveTypes.Int8, arrow.PrimitiveTypes.Int8})
   345  	assert.NoError(t, err)
   346  	assert.Same(t, arrow.PrimitiveTypes.Int32, result)
   347  
   348  	resolver := func(_ *exec.KernelCtx, args []arrow.DataType) (arrow.DataType, error) {
   349  		return args[0], nil
   350  	}
   351  	ty2 := exec.NewComputedOutputType(resolver)
   352  
   353  	result, err = ty2.Resolve(nil, []arrow.DataType{arrow.BinaryTypes.String})
   354  	assert.NoError(t, err)
   355  	assert.Same(t, arrow.BinaryTypes.String, result)
   356  
   357  	// type resolver that returns an error
   358  	ty3 := exec.NewComputedOutputType(func(_ *exec.KernelCtx, dt []arrow.DataType) (arrow.DataType, error) {
   359  		// checking the value types versus the function arity should be validated
   360  		// elsewhere. this is just for illustration purposes
   361  		if len(dt) == 0 {
   362  			return nil, fmt.Errorf("%w: need at least one argument", arrow.ErrInvalid)
   363  		}
   364  		return dt[0], nil
   365  	})
   366  
   367  	_, err = ty3.Resolve(nil, []arrow.DataType{})
   368  	assert.ErrorIs(t, err, arrow.ErrInvalid)
   369  
   370  	// resolver returns a fixed value
   371  	ty4 := exec.NewComputedOutputType(func(*exec.KernelCtx, []arrow.DataType) (arrow.DataType, error) {
   372  		return arrow.PrimitiveTypes.Int32, nil
   373  	})
   374  	result, err = ty4.Resolve(nil, []arrow.DataType{arrow.PrimitiveTypes.Int8})
   375  	assert.NoError(t, err)
   376  	assert.Same(t, arrow.PrimitiveTypes.Int32, result)
   377  	result, err = ty4.Resolve(nil, []arrow.DataType{})
   378  	assert.NoError(t, err)
   379  	assert.Same(t, arrow.PrimitiveTypes.Int32, result)
   380  }
   381  
   382  func TestKernelSignatureEquals(t *testing.T) {
   383  	sig1 := exec.KernelSignature{
   384  		InputTypes: []exec.InputType{},
   385  		OutType:    exec.NewOutputType(arrow.BinaryTypes.String)}
   386  	sig1Copy := exec.KernelSignature{
   387  		InputTypes: []exec.InputType{},
   388  		OutType:    exec.NewOutputType(arrow.BinaryTypes.String)}
   389  	sig2 := exec.KernelSignature{
   390  		InputTypes: []exec.InputType{
   391  			exec.NewExactInput(arrow.PrimitiveTypes.Int8)},
   392  		OutType: exec.NewOutputType(arrow.BinaryTypes.String),
   393  	}
   394  
   395  	// output type doesn't matter (for now)
   396  	sig3 := exec.KernelSignature{
   397  		InputTypes: []exec.InputType{
   398  			exec.NewExactInput(arrow.PrimitiveTypes.Int8)},
   399  		OutType: exec.NewOutputType(arrow.PrimitiveTypes.Int32),
   400  	}
   401  
   402  	sig4 := exec.KernelSignature{
   403  		InputTypes: []exec.InputType{
   404  			exec.NewExactInput(arrow.PrimitiveTypes.Int8),
   405  			exec.NewExactInput(arrow.PrimitiveTypes.Int16),
   406  		},
   407  		OutType: exec.NewOutputType(arrow.BinaryTypes.String),
   408  	}
   409  	sig4Copy := exec.KernelSignature{
   410  		InputTypes: []exec.InputType{
   411  			exec.NewExactInput(arrow.PrimitiveTypes.Int8),
   412  			exec.NewExactInput(arrow.PrimitiveTypes.Int16),
   413  		},
   414  		OutType: exec.NewOutputType(arrow.BinaryTypes.String),
   415  	}
   416  	sig5 := exec.KernelSignature{
   417  		InputTypes: []exec.InputType{
   418  			exec.NewExactInput(arrow.PrimitiveTypes.Int8),
   419  			exec.NewExactInput(arrow.PrimitiveTypes.Int16),
   420  			exec.NewExactInput(arrow.PrimitiveTypes.Int32),
   421  		},
   422  		OutType: exec.NewOutputType(arrow.BinaryTypes.String),
   423  	}
   424  
   425  	assert.True(t, sig1.Equals(sig1))
   426  	assert.True(t, sig2.Equals(sig3))
   427  	assert.False(t, sig3.Equals(sig4))
   428  
   429  	// different sig objects but same sig
   430  	assert.True(t, sig1.Equals(sig1Copy))
   431  	assert.True(t, sig4.Equals(sig4Copy))
   432  
   433  	// match first 2 args, but not third
   434  	assert.False(t, sig4.Equals(sig5))
   435  }
   436  
   437  func TestKernelSignatureVarArgsEqual(t *testing.T) {
   438  	sig1 := exec.KernelSignature{
   439  		InputTypes: []exec.InputType{exec.NewExactInput(arrow.PrimitiveTypes.Int8)},
   440  		OutType:    exec.NewOutputType(arrow.BinaryTypes.String),
   441  		IsVarArgs:  true,
   442  	}
   443  	sig2 := exec.KernelSignature{
   444  		InputTypes: []exec.InputType{exec.NewExactInput(arrow.PrimitiveTypes.Int8)},
   445  		OutType:    exec.NewOutputType(arrow.BinaryTypes.String),
   446  		IsVarArgs:  true,
   447  	}
   448  	sig3 := exec.KernelSignature{
   449  		InputTypes: []exec.InputType{exec.NewExactInput(arrow.PrimitiveTypes.Int8)},
   450  		OutType:    exec.NewOutputType(arrow.BinaryTypes.String),
   451  	}
   452  
   453  	assert.True(t, sig1.Equals(sig2))
   454  	assert.False(t, sig2.Equals(sig3))
   455  }
   456  
   457  func TestKernelSignatureHash(t *testing.T) {
   458  	sig1 := exec.KernelSignature{
   459  		InputTypes: []exec.InputType{},
   460  		OutType:    exec.NewOutputType(arrow.BinaryTypes.String),
   461  	}
   462  	sig2 := exec.KernelSignature{
   463  		InputTypes: []exec.InputType{exec.NewExactInput(arrow.PrimitiveTypes.Int8)},
   464  		OutType:    exec.NewOutputType(arrow.BinaryTypes.String),
   465  	}
   466  	sig3 := exec.KernelSignature{
   467  		InputTypes: []exec.InputType{
   468  			exec.NewExactInput(arrow.PrimitiveTypes.Int8),
   469  			exec.NewExactInput(arrow.PrimitiveTypes.Int32)},
   470  		OutType: exec.NewOutputType(arrow.BinaryTypes.String),
   471  	}
   472  
   473  	assert.Equal(t, sig1.Hash(), sig1.Hash())
   474  	assert.Equal(t, sig2.Hash(), sig2.Hash())
   475  	assert.NotEqual(t, sig1.Hash(), sig2.Hash())
   476  	assert.NotEqual(t, sig2.Hash(), sig3.Hash())
   477  }
   478  
   479  func TestKernelSignatureMatchesInputs(t *testing.T) {
   480  	// () -> boolean
   481  	sig1 := exec.KernelSignature{
   482  		OutType: exec.NewOutputType(arrow.FixedWidthTypes.Boolean)}
   483  
   484  	assert.True(t, sig1.MatchesInputs([]arrow.DataType{}))
   485  	assert.False(t, sig1.MatchesInputs([]arrow.DataType{arrow.PrimitiveTypes.Int8}))
   486  
   487  	// (int8, decimal) -> boolean
   488  	sig2 := exec.KernelSignature{
   489  		InputTypes: []exec.InputType{
   490  			exec.NewExactInput(arrow.PrimitiveTypes.Int8),
   491  			exec.NewIDInput(arrow.DECIMAL)},
   492  		OutType: exec.NewOutputType(arrow.FixedWidthTypes.Boolean),
   493  	}
   494  	assert.False(t, sig2.MatchesInputs([]arrow.DataType{}))
   495  	assert.False(t, sig2.MatchesInputs([]arrow.DataType{arrow.PrimitiveTypes.Int8}))
   496  	assert.True(t, sig2.MatchesInputs([]arrow.DataType{
   497  		arrow.PrimitiveTypes.Int8,
   498  		&arrow.Decimal128Type{Precision: 12, Scale: 2}}))
   499  
   500  	// (int8, int32) -> boolean
   501  	sig3 := exec.KernelSignature{
   502  		InputTypes: []exec.InputType{
   503  			exec.NewExactInput(arrow.PrimitiveTypes.Int8),
   504  			exec.NewExactInput(arrow.PrimitiveTypes.Int32),
   505  		},
   506  		OutType: exec.NewOutputType(arrow.FixedWidthTypes.Boolean),
   507  	}
   508  	assert.False(t, sig3.MatchesInputs(nil))
   509  	assert.True(t, sig3.MatchesInputs([]arrow.DataType{arrow.PrimitiveTypes.Int8, arrow.PrimitiveTypes.Int32}))
   510  	assert.False(t, sig3.MatchesInputs([]arrow.DataType{arrow.PrimitiveTypes.Int8, arrow.PrimitiveTypes.Int16}))
   511  }
   512  
   513  func TestKernelSignatureVarArgsMatchesInputs(t *testing.T) {
   514  	{
   515  		sig := exec.KernelSignature{
   516  			InputTypes: []exec.InputType{exec.NewExactInput(arrow.PrimitiveTypes.Int8)},
   517  			OutType:    exec.NewOutputType(arrow.BinaryTypes.String),
   518  			IsVarArgs:  true,
   519  		}
   520  
   521  		args := []arrow.DataType{arrow.PrimitiveTypes.Int8}
   522  		assert.True(t, sig.MatchesInputs(args))
   523  		args = append(args, arrow.PrimitiveTypes.Int8, arrow.PrimitiveTypes.Int8)
   524  		assert.True(t, sig.MatchesInputs(args))
   525  		args = append(args, arrow.PrimitiveTypes.Int32)
   526  		assert.False(t, sig.MatchesInputs(args))
   527  	}
   528  	{
   529  		sig := exec.KernelSignature{
   530  			InputTypes: []exec.InputType{
   531  				exec.NewExactInput(arrow.PrimitiveTypes.Int8),
   532  				exec.NewExactInput(arrow.BinaryTypes.String),
   533  			},
   534  			OutType:   exec.NewOutputType(arrow.BinaryTypes.String),
   535  			IsVarArgs: true,
   536  		}
   537  
   538  		args := []arrow.DataType{arrow.PrimitiveTypes.Int8}
   539  		assert.True(t, sig.MatchesInputs(args))
   540  		args = append(args, arrow.BinaryTypes.String, arrow.BinaryTypes.String)
   541  		assert.True(t, sig.MatchesInputs(args))
   542  		args = append(args, arrow.PrimitiveTypes.Int32)
   543  		assert.False(t, sig.MatchesInputs(args))
   544  	}
   545  }
   546  
   547  func TestKernelSignatureToString(t *testing.T) {
   548  	inTypes := []exec.InputType{
   549  		exec.NewExactInput(arrow.PrimitiveTypes.Int8),
   550  		exec.NewIDInput(arrow.DECIMAL),
   551  		exec.NewExactInput(arrow.BinaryTypes.String),
   552  	}
   553  
   554  	sig := exec.KernelSignature{
   555  		InputTypes: inTypes, OutType: exec.NewOutputType(arrow.BinaryTypes.String),
   556  	}
   557  	assert.Equal(t, "(int8, Type::DECIMAL128, utf8) -> utf8", sig.String())
   558  
   559  	outType := exec.NewComputedOutputType(func(*exec.KernelCtx, []arrow.DataType) (arrow.DataType, error) {
   560  		return nil, arrow.ErrInvalid
   561  	})
   562  	sig2 := exec.KernelSignature{
   563  		InputTypes: []exec.InputType{
   564  			exec.NewExactInput(arrow.PrimitiveTypes.Int8),
   565  			exec.NewIDInput(arrow.DECIMAL)},
   566  		OutType: outType,
   567  	}
   568  	assert.Equal(t, "(int8, Type::DECIMAL128) -> computed", sig2.String())
   569  }
   570  
   571  func TestKernelSignatureVarArgsToString(t *testing.T) {
   572  	sig1 := exec.KernelSignature{
   573  		InputTypes: []exec.InputType{
   574  			exec.NewExactInput(arrow.PrimitiveTypes.Int8)},
   575  		OutType:   exec.NewOutputType(arrow.BinaryTypes.String),
   576  		IsVarArgs: true,
   577  	}
   578  	assert.Equal(t, "varargs[int8*] -> utf8", sig1.String())
   579  
   580  	sig2 := exec.KernelSignature{
   581  		InputTypes: []exec.InputType{
   582  			exec.NewExactInput(arrow.BinaryTypes.String),
   583  			exec.NewExactInput(arrow.PrimitiveTypes.Int8)},
   584  		OutType:   exec.NewOutputType(arrow.BinaryTypes.String),
   585  		IsVarArgs: true,
   586  	}
   587  	assert.Equal(t, "varargs[utf8, int8*] -> utf8", sig2.String())
   588  }