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 }