From 121eb13ec3066a7f0e868fb80695d527ec1d8973 Mon Sep 17 00:00:00 2001 From: Arkadii Kravchuk Date: Sat, 3 Oct 2026 06:23:18 +0300 Subject: [PATCH] DX-126900: [Java][Gandiva] Report time64 types as TIME64 in the expression registry ArrowToProtobuf mapped arrow::Type::TIME64 to GandivaType::TIME32, so Java saw Time(MICROSECOND, 32) / Time(NANOSECOND, 32) instead of the 64-bit types and could never match Gandiva's time64 function signatures. Co-Authored-By: Claude Opus 5.5 --- .../main/cpp/expression_registry_helper.cc | 2 +- .../evaluator/ExpressionRegistryTest.java | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/gandiva/src/main/cpp/expression_registry_helper.cc b/gandiva/src/main/cpp/expression_registry_helper.cc index 21077ff1db..dd9dedacd6 100644 --- a/gandiva/src/main/cpp/expression_registry_helper.cc +++ b/gandiva/src/main/cpp/expression_registry_helper.cc @@ -110,7 +110,7 @@ void ArrowToProtobuf(DataTypePtr type, gandiva::types::ExtGandivaType* gandiva_d break; } case arrow::Type::TIME64: { - gandiva_data_type->set_type(gandiva::types::GandivaType::TIME32); + gandiva_data_type->set_type(gandiva::types::GandivaType::TIME64); std::shared_ptr cast_time_64_type = std::dynamic_pointer_cast(type); arrow::TimeUnit::type unit = cast_time_64_type->unit(); diff --git a/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/ExpressionRegistryTest.java b/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/ExpressionRegistryTest.java index 58279b15c3..6a5de17869 100644 --- a/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/ExpressionRegistryTest.java +++ b/gandiva/src/test/java/org/apache/arrow/gandiva/evaluator/ExpressionRegistryTest.java @@ -16,11 +16,13 @@ */ package org.apache.arrow.gandiva.evaluator; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import com.google.common.collect.Lists; import java.util.Set; import org.apache.arrow.gandiva.exceptions.GandivaException; +import org.apache.arrow.vector.types.TimeUnit; import org.apache.arrow.vector.types.pojo.ArrowType; import org.junit.jupiter.api.Test; @@ -33,6 +35,36 @@ public void testTypes() throws GandivaException { assertTrue(types.contains(uint8)); } + @Test + public void testTimeTypesKeepBitWidth() throws GandivaException { + Set types = ExpressionRegistry.getInstance().getSupportedTypes(); + assertTrue(types.contains(new ArrowType.Time(TimeUnit.SECOND, 32))); + assertTrue(types.contains(new ArrowType.Time(TimeUnit.MILLISECOND, 32))); + assertTrue(types.contains(new ArrowType.Time(TimeUnit.MICROSECOND, 64))); + assertTrue(types.contains(new ArrowType.Time(TimeUnit.NANOSECOND, 64))); + // Time64 units used to be reported with a 32-bit width. + assertFalse(types.contains(new ArrowType.Time(TimeUnit.MICROSECOND, 32))); + assertFalse(types.contains(new ArrowType.Time(TimeUnit.NANOSECOND, 32))); + } + + @Test + public void testTime64Functions() throws GandivaException { + // Time64 signatures are registered with MICROSECOND; NANOSECOND arguments match the + // same signature in Gandiva and are remapped at codegen time. + ArrowType.Time timeMicro = new ArrowType.Time(TimeUnit.MICROSECOND, 64); + ArrowType.Int int64 = new ArrowType.Int(64, true); + ArrowType.Bool bool = new ArrowType.Bool(); + Set functions = ExpressionRegistry.getInstance().getSupportedFunctions(); + assertTrue( + functions.contains( + new FunctionSignature("extractHour", int64, Lists.newArrayList(timeMicro)))); + assertTrue( + functions.contains( + new FunctionSignature("less_than", bool, Lists.newArrayList(timeMicro, timeMicro)))); + assertTrue( + functions.contains(new FunctionSignature("isnull", bool, Lists.newArrayList(timeMicro)))); + } + @Test public void testFunctions() throws GandivaException { ArrowType.Int uint8 = new ArrowType.Int(8, false);