Skip to content

Commit

Permalink
Merge pull request apache#26 from rafael-telles/change-interval-behav…
Browse files Browse the repository at this point in the history
…iour-for-getObject-getString

[JAVA] [JDBC] Change IntervalAccessor getString format
  • Loading branch information
rafael-telles authored Apr 8, 2022
2 parents c881c1c + 7bac8d2 commit 44796fa
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 9 deletions.
6 changes: 6 additions & 0 deletions java/flight/flight-jdbc-driver/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.61</version>
</dependency>

<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.10.14</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@

package org.apache.arrow.driver.jdbc.accessor.impl.calendar;

import static org.apache.arrow.driver.jdbc.utils.IntervalStringUtils.formatIntervalDay;
import static org.apache.arrow.driver.jdbc.utils.IntervalStringUtils.formatIntervalYear;
import static org.joda.time.Period.parse;

import java.sql.SQLException;
import java.time.Duration;
import java.time.Period;
import java.util.function.IntSupplier;
Expand Down Expand Up @@ -91,15 +96,20 @@ public Class<?> getObjectClass() {
}

@Override
public String getString() {
StringBuilder stringBuilder = stringBuilderGetter.get(getCurrentRow());
public String getString() throws SQLException {
Object object = getObject();

this.wasNull = stringBuilder == null;
this.wasNull = object == null;
this.wasNullConsumer.setWasNull(this.wasNull);
if (stringBuilder == null) {
if (object == null) {
return null;
}

return stringBuilder.toString();
if (vector instanceof IntervalDayVector) {
return formatIntervalDay(parse(object.toString()));
} else if (vector instanceof IntervalYearVector) {
return formatIntervalYear(parse(object.toString()));
} else {
throw new SQLException("Invalid Interval vector instance");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.arrow.driver.jdbc.utils;

import org.apache.arrow.vector.util.DateUtility;
import org.joda.time.Period;

/**
* Utility class to format periods similar to Oracle's representation
* of "INTERVAL * to *" data type.
*/
public final class IntervalStringUtils {

/**
* Constructor Method of class.
*/
private IntervalStringUtils( ) {}

/**
* Formats a period similar to Oracle INTERVAL YEAR TO MONTH data type<br>.
* For example, the string "+21-02" defines an interval of 21 years and 2 months.
*/
public static String formatIntervalYear(final Period p) {
long months = p.getYears() * (long) DateUtility.yearsToMonths + p.getMonths();
boolean neg = false;
if (months < 0) {
months = -months;
neg = true;
}
final int years = (int) (months / DateUtility.yearsToMonths);
months = months % DateUtility.yearsToMonths;

return String.format("%c%03d-%02d", neg ? '-' : '+', years, months);
}

/**
* Formats a period similar to Oracle INTERVAL DAY TO SECOND data type.<br>.
* For example, the string "-001 18:25:16.766" defines an interval of
* - 1 day 18 hours 25 minutes 16 seconds and 766 milliseconds.
*/
public static String formatIntervalDay(final Period p) {
long millis = p.getDays() * (long) DateUtility.daysToStandardMillis + millisFromPeriod(p);

boolean neg = false;
if (millis < 0) {
millis = -millis;
neg = true;
}

final int days = (int) (millis / DateUtility.daysToStandardMillis);
millis = millis % DateUtility.daysToStandardMillis;

final int hours = (int) (millis / DateUtility.hoursToMillis);
millis = millis % DateUtility.hoursToMillis;

final int minutes = (int) (millis / DateUtility.minutesToMillis);
millis = millis % DateUtility.minutesToMillis;

final int seconds = (int) (millis / DateUtility.secondsToMillis);
millis = millis % DateUtility.secondsToMillis;

return String.format("%c%03d %02d:%02d:%02d.%03d", neg ? '-' : '+', days, hours, minutes, seconds, millis);
}

public static int millisFromPeriod(Period period) {
return period.getHours() * DateUtility.hoursToMillis + period.getMinutes() * DateUtility.minutesToMillis +
period.getSeconds() * DateUtility.secondsToMillis + period.getMillis();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@

package org.apache.arrow.driver.jdbc.accessor.impl.calendar;

import static org.apache.arrow.driver.jdbc.utils.IntervalStringUtils.formatIntervalDay;
import static org.apache.arrow.driver.jdbc.utils.IntervalStringUtils.formatIntervalYear;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.joda.time.Period.parse;

import java.time.Duration;
import java.time.Period;
Expand All @@ -33,6 +36,7 @@
import org.apache.arrow.vector.IntervalYearVector;
import org.apache.arrow.vector.ValueVector;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Rule;
Expand Down Expand Up @@ -134,14 +138,53 @@ public void testShouldGetObjectReturnNull() throws Exception {
}

private String getStringOnVector(ValueVector vector, int index) {
if (vector instanceof IntervalDayVector) {
return ((IntervalDayVector) vector).getAsStringBuilder(index).toString();
String object = getExpectedObject(vector, index).toString();
if (object == null) {
return null;
} else if (vector instanceof IntervalDayVector) {
return formatIntervalDay(parse(object));
} else if (vector instanceof IntervalYearVector) {
return ((IntervalYearVector) vector).getAsStringBuilder(index).toString();
return formatIntervalYear(parse(object));
}
return null;
}

@Test
public void testShouldGetIntervalYear( ) {
Assert.assertEquals("-002-00", formatIntervalYear(parse("P-2Y")));
Assert.assertEquals("-001-01", formatIntervalYear(parse("P-1Y-1M")));
Assert.assertEquals("-001-02", formatIntervalYear(parse("P-1Y-2M")));
Assert.assertEquals("-002-03", formatIntervalYear(parse("P-2Y-3M")));
Assert.assertEquals("-002-04", formatIntervalYear(parse("P-2Y-4M")));
Assert.assertEquals("-011-01", formatIntervalYear(parse("P-11Y-1M")));
Assert.assertEquals("+002-00", formatIntervalYear(parse("P+2Y")));
Assert.assertEquals("+001-01", formatIntervalYear(parse("P+1Y1M")));
Assert.assertEquals("+001-02", formatIntervalYear(parse("P+1Y2M")));
Assert.assertEquals("+002-03", formatIntervalYear(parse("P+2Y3M")));
Assert.assertEquals("+002-04", formatIntervalYear(parse("P+2Y4M")));
Assert.assertEquals("+011-01", formatIntervalYear(parse("P+11Y1M")));
}

@Test
public void testShouldGetIntervalDay( ) {
Assert.assertEquals("-000 01:00:00.000", formatIntervalDay(parse("PT-1H")));
Assert.assertEquals("-000 01:00:00.001", formatIntervalDay(parse("PT-1H-0M-00.001S")));
Assert.assertEquals("-000 01:01:01.000", formatIntervalDay(parse("PT-1H-1M-1S")));
Assert.assertEquals("-000 02:02:02.002", formatIntervalDay(parse("PT-2H-2M-02.002S")));
Assert.assertEquals("-000 23:59:59.999", formatIntervalDay(parse("PT-23H-59M-59.999S")));
Assert.assertEquals("-000 11:59:00.100", formatIntervalDay(parse("PT-11H-59M-00.100S")));
Assert.assertEquals("-000 05:02:03.000", formatIntervalDay(parse("PT-5H-2M-3S")));
Assert.assertEquals("-000 22:22:22.222", formatIntervalDay(parse("PT-22H-22M-22.222S")));
Assert.assertEquals("+000 01:00:00.000", formatIntervalDay(parse("PT+1H")));
Assert.assertEquals("+000 01:00:00.001", formatIntervalDay(parse("PT+1H0M00.001S")));
Assert.assertEquals("+000 01:01:01.000", formatIntervalDay(parse("PT+1H1M1S")));
Assert.assertEquals("+000 02:02:02.002", formatIntervalDay(parse("PT+2H2M02.002S")));
Assert.assertEquals("+000 23:59:59.999", formatIntervalDay(parse("PT+23H59M59.999S")));
Assert.assertEquals("+000 11:59:00.100", formatIntervalDay(parse("PT+11H59M00.100S")));
Assert.assertEquals("+000 05:02:03.000", formatIntervalDay(parse("PT+5H2M3S")));
Assert.assertEquals("+000 22:22:22.222", formatIntervalDay(parse("PT+22H22M22.222S")));
}

@Test
public void testShouldGetStringReturnCorrectString() throws Exception {
accessorIterator.assertAccessorGetter(vector, ArrowFlightJdbcIntervalVectorAccessor::getString,
Expand Down

0 comments on commit 44796fa

Please sign in to comment.