diff --git a/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcTimeStampVectorAccessorTest.java b/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcTimeStampVectorAccessorTest.java index 2e329f148e66c..392e1fea8f891 100644 --- a/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcTimeStampVectorAccessorTest.java +++ b/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/accessor/impl/calendar/ArrowFlightJdbcTimeStampVectorAccessorTest.java @@ -132,6 +132,11 @@ public static Stream data() { () -> rootAllocatorTestExtension.createTimeStampMilliTZVector(ASIA_BANGKOK), "TimeStampMilliTZVector", ASIA_BANGKOK), + Arguments.of( + (Supplier) + () -> rootAllocatorTestExtension.createTimeStampWithPrecisionVector(), + "TimeStampWithPrecisionVector", + null), Arguments.of( (Supplier) () -> rootAllocatorTestExtension.createTimeStampSecVector(), "TimeStampSecVector", diff --git a/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/RootAllocatorTestExtension.java b/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/RootAllocatorTestExtension.java index 347e92a16c4e5..64ff15b7ac899 100644 --- a/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/RootAllocatorTestExtension.java +++ b/java/flight/flight-sql-jdbc-core/src/test/java/org/apache/arrow/driver/jdbc/utils/RootAllocatorTestExtension.java @@ -48,6 +48,7 @@ import org.apache.arrow.vector.TimeStampNanoVector; import org.apache.arrow.vector.TimeStampSecTZVector; import org.apache.arrow.vector.TimeStampSecVector; +import org.apache.arrow.vector.TimeStampWithPrecisionVector; import org.apache.arrow.vector.TinyIntVector; import org.apache.arrow.vector.UInt1Vector; import org.apache.arrow.vector.UInt2Vector; @@ -60,6 +61,8 @@ import org.apache.arrow.vector.complex.impl.UnionFixedSizeListWriter; import org.apache.arrow.vector.complex.impl.UnionLargeListWriter; import org.apache.arrow.vector.complex.impl.UnionListWriter; +import org.apache.arrow.vector.types.pojo.ArrowType.TimestampWithPrecision; +import org.apache.arrow.vector.types.pojo.FieldType; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; @@ -630,6 +633,18 @@ public TimeStampMilliTZVector createTimeStampMilliTZVector(String timeZone) { return valueVector; } + public TimeStampWithPrecisionVector createTimeStampWithPrecisionVector() { + TimeStampWithPrecisionVector valueVector = + new TimeStampWithPrecisionVector( + "", FieldType.nullable(new TimestampWithPrecision(9, null)), this.getRootAllocator()); + valueVector.allocateNew(2); + valueVector.setSafe(0, TimeUnit.MILLISECONDS.toNanos(1625702400000L)); + valueVector.setSafe(1, TimeUnit.MILLISECONDS.toNanos(1625788800000L)); + valueVector.setValueCount(2); + + return valueVector; + } + public TimeStampSecVector createTimeStampSecVector() { TimeStampSecVector valueVector = new TimeStampSecVector("", this.getRootAllocator()); valueVector.allocateNew(2); diff --git a/java/vector/src/main/java/org/apache/arrow/vector/GenerateSampleData.java b/java/vector/src/main/java/org/apache/arrow/vector/GenerateSampleData.java index e8250f9f57f2a..a6510ce35b752 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/GenerateSampleData.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/GenerateSampleData.java @@ -73,6 +73,8 @@ public static void generateTestData(final ValueVector vector, final int valueCou writeTimeStampData((TimeStampMilliVector) vector, valueCount); } else if (vector instanceof TimeStampNanoVector) { writeTimeStampData((TimeStampNanoVector) vector, valueCount); + } else if (vector instanceof TimeStampWithPrecisionVector) { + writeTimeStampData((TimeStampWithPrecisionVector) vector, valueCount); } else if (vector instanceof TimeStampSecTZVector) { writeTimeStampData((TimeStampSecTZVector) vector, valueCount); } else if (vector instanceof TimeStampMicroTZVector) { diff --git a/java/vector/src/main/java/org/apache/arrow/vector/ipc/JsonFileReader.java b/java/vector/src/main/java/org/apache/arrow/vector/ipc/JsonFileReader.java index 5668325a87eeb..4fdd7341714a0 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/ipc/JsonFileReader.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/ipc/JsonFileReader.java @@ -808,6 +808,7 @@ private List readIntoBuffer( case TIMENANO: reader = helper.INT8; break; + case TIMESTAMPWITHPRECISION: case TIMESTAMPNANO: case TIMESTAMPMICRO: case TIMESTAMPMILLI: diff --git a/java/vector/src/main/java/org/apache/arrow/vector/ipc/JsonFileWriter.java b/java/vector/src/main/java/org/apache/arrow/vector/ipc/JsonFileWriter.java index 68700fe6afd25..13d6864b292cf 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/ipc/JsonFileWriter.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/ipc/JsonFileWriter.java @@ -66,6 +66,7 @@ import org.apache.arrow.vector.TimeStampNanoVector; import org.apache.arrow.vector.TimeStampSecTZVector; import org.apache.arrow.vector.TimeStampSecVector; +import org.apache.arrow.vector.TimeStampWithPrecisionVector; import org.apache.arrow.vector.TinyIntVector; import org.apache.arrow.vector.TypeLayout; import org.apache.arrow.vector.UInt1Vector; @@ -507,6 +508,9 @@ private void writeValueToGenerator( case TIMESTAMPNANO: generator.writeNumber(TimeStampNanoVector.get(buffer, index)); break; + case TIMESTAMPWITHPRECISION: + generator.writeNumber(TimeStampWithPrecisionVector.get(buffer, index)); + break; case TIMESTAMPSECTZ: generator.writeNumber(TimeStampSecTZVector.get(buffer, index)); break; diff --git a/java/vector/src/main/java/org/apache/arrow/vector/table/Row.java b/java/vector/src/main/java/org/apache/arrow/vector/table/Row.java index b89159b5ee754..ea90df5a7e672 100644 --- a/java/vector/src/main/java/org/apache/arrow/vector/table/Row.java +++ b/java/vector/src/main/java/org/apache/arrow/vector/table/Row.java @@ -56,6 +56,7 @@ import org.apache.arrow.vector.TimeStampNanoVector; import org.apache.arrow.vector.TimeStampSecTZVector; import org.apache.arrow.vector.TimeStampSecVector; +import org.apache.arrow.vector.TimeStampWithPrecisionVector; import org.apache.arrow.vector.TinyIntVector; import org.apache.arrow.vector.UInt1Vector; import org.apache.arrow.vector.UInt2Vector; @@ -93,6 +94,7 @@ import org.apache.arrow.vector.holders.NullableTimeStampNanoTZHolder; import org.apache.arrow.vector.holders.NullableTimeStampSecHolder; import org.apache.arrow.vector.holders.NullableTimeStampSecTZHolder; +import org.apache.arrow.vector.holders.NullableTimeStampWithPrecisionHolder; import org.apache.arrow.vector.holders.NullableTinyIntHolder; import org.apache.arrow.vector.holders.NullableUInt1Holder; import org.apache.arrow.vector.holders.NullableUInt2Holder; @@ -1100,6 +1102,74 @@ public void getTimeStampSecTZ(int columnIndex, NullableTimeStampSecTZHolder hold vector.get(rowNumber, holder); } + /** + * Returns a long from the column of the given name at the current row. An + * IllegalArgumentException is thrown if the column is not present, and a ClassCastException is + * thrown if it is present but has a different type + */ + public long getTimeStampWithPrecision(String columnName) { + TimeStampWithPrecisionVector vector = + (TimeStampWithPrecisionVector) table.getVector(columnName); + return vector.get(rowNumber); + } + + /** + * Returns a long from the column with the given index at the current row. An + * IllegalArgumentException is thrown if the column is not present, and a ClassCastException is + * thrown if it is present but has a different type + */ + public long getTimeStampWithPrecision(int columnIndex) { + TimeStampWithPrecisionVector vector = + (TimeStampWithPrecisionVector) table.getVector(columnIndex); + return vector.get(rowNumber); + } + + /** + * Updates the holder with the value from the column of the given name at the current row. An + * IllegalArgumentException is thrown if the column is not present, and a ClassCastException is + * thrown if it is present but has a different type + */ + public void getTimeStampWithPrecision( + String columnName, NullableTimeStampWithPrecisionHolder holder) { + TimeStampWithPrecisionVector vector = + (TimeStampWithPrecisionVector) table.getVector(columnName); + vector.get(rowNumber, holder); + } + + /** + * Updates the holder with the value from the column with the given index at the current row. An + * IllegalArgumentException is thrown if the column is not present, and a ClassCastException is + * thrown if it is present but has a different type + */ + public void getTimeStampWithPrecision( + int columnIndex, NullableTimeStampWithPrecisionHolder holder) { + TimeStampWithPrecisionVector vector = + (TimeStampWithPrecisionVector) table.getVector(columnIndex); + vector.get(rowNumber, holder); + } + + /** + * Returns a LocalDateTime from the column of the given name at the current row. An + * IllegalArgumentException is thrown if the column is not present, and a ClassCastException is + * thrown if it is present but has a different type + */ + public LocalDateTime getTimeStampWithPrecisionObj(String columnName) { + TimeStampWithPrecisionVector vector = + (TimeStampWithPrecisionVector) table.getVector(columnName); + return vector.getObject(rowNumber); + } + + /** + * Returns a LocalDateTime from the column with the given index at the current row. An + * IllegalArgumentException is thrown if the column is not present, and a ClassCastException is + * thrown if it is present but has a different type + */ + public LocalDateTime getTimeStampWithPrecisionObj(int columnIndex) { + TimeStampWithPrecisionVector vector = + (TimeStampWithPrecisionVector) table.getVector(columnIndex); + return vector.getObject(rowNumber); + } + /** * Returns a long from the column of the given name at the current row. An * IllegalArgumentException is thrown if the column is not present, and a ClassCastException is diff --git a/java/vector/src/test/java/org/apache/arrow/vector/table/RowTest.java b/java/vector/src/test/java/org/apache/arrow/vector/table/RowTest.java index c1125d407e145..beaa339aa619c 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/table/RowTest.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/table/RowTest.java @@ -92,6 +92,7 @@ import org.apache.arrow.vector.holders.NullableTimeStampNanoTZHolder; import org.apache.arrow.vector.holders.NullableTimeStampSecHolder; import org.apache.arrow.vector.holders.NullableTimeStampSecTZHolder; +import org.apache.arrow.vector.holders.NullableTimeStampWithPrecisionHolder; import org.apache.arrow.vector.holders.NullableTinyIntHolder; import org.apache.arrow.vector.holders.NullableUInt1Holder; import org.apache.arrow.vector.holders.NullableUInt2Holder; @@ -549,21 +550,30 @@ void fixedWidthVectorTest() { assertEquals(c.getTimeStampMilli("timeStampMilli_vector"), c.getTimeStampMilli(15)); assertEquals(c.getTimeStampMicro("timeStampMicro_vector"), c.getTimeStampMicro(16)); assertEquals(c.getTimeStampNano("timeStampNano_vector"), c.getTimeStampNano(17)); + assertEquals( + c.getTimeStampWithPrecision("timeStampPrecision_vector"), + c.getTimeStampWithPrecision(18)); // time stamp tests using Nullable Holders NullableTimeStampSecHolder timeStampSecHolder = new NullableTimeStampSecHolder(); NullableTimeStampMilliHolder timeStampMilliHolder = new NullableTimeStampMilliHolder(); NullableTimeStampMicroHolder timeStampMicroHolder = new NullableTimeStampMicroHolder(); NullableTimeStampNanoHolder timeStampNanoHolder = new NullableTimeStampNanoHolder(); + NullableTimeStampWithPrecisionHolder timeStampWithPrecisionHolder = + new NullableTimeStampWithPrecisionHolder(); // fill the holders using vector index and test c.getTimeStampSec(14, timeStampSecHolder); c.getTimeStampMilli(15, timeStampMilliHolder); c.getTimeStampMicro(16, timeStampMicroHolder); c.getTimeStampNano(17, timeStampNanoHolder); + c.getTimeStampWithPrecision(18, timeStampWithPrecisionHolder); assertEquals(c.getTimeStampSec("timeStampSec_vector"), timeStampSecHolder.value); assertEquals(c.getTimeStampMilli("timeStampMilli_vector"), timeStampMilliHolder.value); assertEquals(c.getTimeStampMicro("timeStampMicro_vector"), timeStampMicroHolder.value); assertEquals(c.getTimeStampNano("timeStampNano_vector"), timeStampNanoHolder.value); + assertEquals( + c.getTimeStampWithPrecision("timeStampPrecision_vector"), + timeStampWithPrecisionHolder.value); LocalDateTime secDT = c.getTimeStampSecObj(14); assertNotNull(secDT); @@ -581,15 +591,24 @@ void fixedWidthVectorTest() { assertNotNull(nanoDT); assertEquals(nanoDT, c.getTimeStampNanoObj("timeStampNano_vector")); + LocalDateTime nanoPrecisionDT = c.getTimeStampWithPrecisionObj(18); + assertNotNull(nanoPrecisionDT); + assertEquals(nanoPrecisionDT, c.getTimeStampWithPrecisionObj("timeStampPrecision_vector")); + // refill the holders using vector name and retest c.getTimeStampSec("timeStampSec_vector", timeStampSecHolder); c.getTimeStampMilli("timeStampMilli_vector", timeStampMilliHolder); c.getTimeStampMicro("timeStampMicro_vector", timeStampMicroHolder); c.getTimeStampNano("timeStampNano_vector", timeStampNanoHolder); + c.getTimeStampWithPrecision("timeStampPrecision_vector", timeStampWithPrecisionHolder); + assertEquals(c.getTimeStampSec("timeStampSec_vector"), timeStampSecHolder.value); assertEquals(c.getTimeStampMilli("timeStampMilli_vector"), timeStampMilliHolder.value); assertEquals(c.getTimeStampMicro("timeStampMicro_vector"), timeStampMicroHolder.value); assertEquals(c.getTimeStampNano("timeStampNano_vector"), timeStampNanoHolder.value); + assertEquals( + c.getTimeStampWithPrecision("timeStampPrecision_vector"), + timeStampWithPrecisionHolder.value); } } diff --git a/java/vector/src/test/java/org/apache/arrow/vector/table/TestUtils.java b/java/vector/src/test/java/org/apache/arrow/vector/table/TestUtils.java index d39f92e19880b..2e00723a42076 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/table/TestUtils.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/table/TestUtils.java @@ -54,6 +54,7 @@ import org.apache.arrow.vector.TimeStampNanoVector; import org.apache.arrow.vector.TimeStampSecTZVector; import org.apache.arrow.vector.TimeStampSecVector; +import org.apache.arrow.vector.TimeStampWithPrecisionVector; import org.apache.arrow.vector.TinyIntVector; import org.apache.arrow.vector.UInt1Vector; import org.apache.arrow.vector.UInt2Vector; @@ -74,6 +75,7 @@ import org.apache.arrow.vector.types.TimeUnit; import org.apache.arrow.vector.types.Types; import org.apache.arrow.vector.types.pojo.ArrowType; +import org.apache.arrow.vector.types.pojo.ArrowType.TimestampWithPrecision; import org.apache.arrow.vector.types.pojo.Field; import org.apache.arrow.vector.types.pojo.FieldType; @@ -257,6 +259,11 @@ static List simpleTemporalVectors( vectors.add(new TimeStampMilliVector("timeStampMilli_vector", allocator)); vectors.add(new TimeStampMicroVector("timeStampMicro_vector", allocator)); vectors.add(new TimeStampNanoVector("timeStampNano_vector", allocator)); + vectors.add( + new TimeStampWithPrecisionVector( + "timeStampPrecision_vector", + FieldType.nullable(new TimestampWithPrecision(9, null)), + allocator)); vectors.add(new DateMilliVector("dateMilli_vector", allocator)); vectors.add(new DateDayVector("dateDay_vector", allocator)); diff --git a/java/vector/src/test/java/org/apache/arrow/vector/testing/TestValueVectorPopulator.java b/java/vector/src/test/java/org/apache/arrow/vector/testing/TestValueVectorPopulator.java index c0e2ae252e02c..cc40e2dec47ac 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/testing/TestValueVectorPopulator.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/testing/TestValueVectorPopulator.java @@ -42,6 +42,7 @@ import org.apache.arrow.vector.TimeStampMilliVector; import org.apache.arrow.vector.TimeStampNanoVector; import org.apache.arrow.vector.TimeStampSecVector; +import org.apache.arrow.vector.TimeStampWithPrecisionVector; import org.apache.arrow.vector.TinyIntVector; import org.apache.arrow.vector.UInt1Vector; import org.apache.arrow.vector.UInt2Vector; @@ -52,6 +53,7 @@ import org.apache.arrow.vector.compare.VectorEqualsVisitor; import org.apache.arrow.vector.types.TimeUnit; import org.apache.arrow.vector.types.pojo.ArrowType; +import org.apache.arrow.vector.types.pojo.ArrowType.TimestampWithPrecision; import org.apache.arrow.vector.types.pojo.FieldType; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -457,6 +459,29 @@ public void testPopulateTimeStampNanoVector() { } } + @Test + public void testPopulateTimeStampPrecisionVector() { + try (final TimeStampWithPrecisionVector vector1 = + new TimeStampWithPrecisionVector( + "vector", FieldType.nullable(new TimestampWithPrecision(9, null)), allocator); + final TimeStampWithPrecisionVector vector2 = + new TimeStampWithPrecisionVector( + "vector", FieldType.nullable(new TimestampWithPrecision(9, null)), allocator)) { + + vector1.allocateNew(10); + for (int i = 0; i < 10; i++) { + if (i % 2 == 0) { + vector1.setNull(i); + } else { + vector1.set(i, i * 10000); + } + } + vector1.setValueCount(10); + setVector(vector2, null, 10000L, null, 30000L, null, 50000L, null, 70000L, null, 90000L); + assertTrue(VectorEqualsVisitor.vectorEquals(vector1, vector2)); + } + } + @Test public void testPopulateTimeStampSecVector() { try (final TimeStampSecVector vector1 = new TimeStampSecVector("vector", allocator); diff --git a/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java b/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java index afbc30f019ef6..578d8c0a31705 100644 --- a/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java +++ b/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java @@ -52,6 +52,7 @@ import org.apache.arrow.vector.TimeStampNanoVector; import org.apache.arrow.vector.TimeStampSecTZVector; import org.apache.arrow.vector.TimeStampSecVector; +import org.apache.arrow.vector.TimeStampWithPrecisionVector; import org.apache.arrow.vector.TinyIntVector; import org.apache.arrow.vector.UInt1Vector; import org.apache.arrow.vector.UInt2Vector; @@ -453,6 +454,22 @@ public static void setVector(TimeStampNanoVector vector, Long... values) { vector.setValueCount(length); } + /** + * Populate values for TimeStampNanoVector. + * + * @param values numbers of nanoseconds since UNIX epoch + */ + public static void setVector(TimeStampWithPrecisionVector vector, Long... values) { + final int length = values.length; + vector.allocateNew(length); + for (int i = 0; i < length; i++) { + if (values[i] != null) { + vector.set(i, values[i]); + } + } + vector.setValueCount(length); + } + /** * Populate values for TimeStampSecTZVector. *