This is an automated email from the ASF dual-hosted git repository.

mbudiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite-avatica.git


The following commit(s) were added to refs/heads/main by this push:
     new 8c36e0196 [CALCITE-6282] Avatica ignores time precision when returning 
TIME results
8c36e0196 is described below

commit 8c36e0196d10574280518d406f288a3bd83ae4dc
Author: Mihai Budiu <[email protected]>
AuthorDate: Sun Feb 25 03:57:38 2024 -0800

    [CALCITE-6282] Avatica ignores time precision when returning TIME results
    
    Signed-off-by: Mihai Budiu <[email protected]>
---
 .../calcite/avatica/util/AbstractCursor.java       | 43 +++++++++++++---------
 .../avatica/util/TimeFromNumberAccessorTest.java   | 24 +++++++++++-
 .../avatica/util/TimestampAccessorTest.java        |  2 +-
 .../util/TimestampFromNumberAccessorTest.java      | 31 +++++++++++++++-
 .../util/TimestampFromUtilDateAccessorTest.java    |  2 +-
 5 files changed, 81 insertions(+), 21 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java 
b/core/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
index 2a4cd64ce..2c5653ae0 100644
--- a/core/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
+++ b/core/src/main/java/org/apache/calcite/avatica/util/AbstractCursor.java
@@ -154,7 +154,7 @@ public abstract class AbstractCursor implements Cursor {
       case PRIMITIVE_INT:
       case INTEGER:
       case NUMBER:
-        return new TimeFromNumberAccessor(getter, localCalendar);
+        return new TimeFromNumberAccessor(getter, localCalendar, 
columnMetaData.precision);
       case JAVA_SQL_TIME:
         return new TimeAccessor(getter, localCalendar);
       default:
@@ -165,11 +165,11 @@ public abstract class AbstractCursor implements Cursor {
       case PRIMITIVE_LONG:
       case LONG:
       case NUMBER:
-        return new TimestampFromNumberAccessor(getter, localCalendar);
+        return new TimestampFromNumberAccessor(getter, localCalendar, 
columnMetaData.precision);
       case JAVA_SQL_TIMESTAMP:
-        return new TimestampAccessor(getter, localCalendar);
+        return new TimestampAccessor(getter, localCalendar, 
columnMetaData.precision);
       case JAVA_UTIL_DATE:
-        return new TimestampFromUtilDateAccessor(getter, localCalendar);
+        return new TimestampFromUtilDateAccessor(getter, localCalendar, 
columnMetaData.precision);
       default:
         throw new AssertionError("bad " + columnMetaData.type.rep);
       }
@@ -241,11 +241,11 @@ public abstract class AbstractCursor implements Cursor {
   /** Accesses a timestamp value as a string.
    * The timestamp is in SQL format (e.g. "2013-09-22 22:30:32"),
    * not Java format ("2013-09-22 22:30:32.123"). */
-  private static String timestampAsString(long v, Calendar calendar) {
+  private static String timestampAsString(long v, Calendar calendar, int 
precision) {
     if (calendar != null) {
       v -= calendar.getTimeZone().getOffset(v);
     }
-    return DateTimeUtils.unixTimestampToString(v);
+    return DateTimeUtils.unixTimestampToString(v, precision);
   }
 
   /** Accesses a date value as a string, e.g. "2013-09-22". */
@@ -255,11 +255,11 @@ public abstract class AbstractCursor implements Cursor {
   }
 
   /** Accesses a time value as a string, e.g. "22:30:32". */
-  private static String timeAsString(int v, Calendar calendar) {
+  private static String timeAsString(int v, Calendar calendar, int precision) {
     if (calendar != null) {
       v -= calendar.getTimeZone().getOffset(v);
     }
-    return DateTimeUtils.unixTimeToString(v);
+    return DateTimeUtils.unixTimeToString(v, precision);
   }
 
   /** Implementation of {@link Cursor.Accessor}. */
@@ -955,10 +955,12 @@ public abstract class AbstractCursor implements Cursor {
    */
   static class TimeFromNumberAccessor extends NumberAccessor {
     private final Calendar localCalendar;
+    private final int precision;
 
-    TimeFromNumberAccessor(Getter getter, Calendar localCalendar) {
+    TimeFromNumberAccessor(Getter getter, Calendar localCalendar, int 
precision) {
       super(getter, 0);
       this.localCalendar = localCalendar;
+      this.precision = precision;
     }
 
     @Override public Object getObject() throws SQLException {
@@ -986,7 +988,7 @@ public abstract class AbstractCursor implements Cursor {
       if (v == null) {
         return null;
       }
-      return timeAsString(v.intValue(), null);
+      return timeAsString(v.intValue(), null, this.precision);
     }
 
     protected Number getNumber() throws SQLException {
@@ -1013,10 +1015,12 @@ public abstract class AbstractCursor implements Cursor {
    */
   static class TimestampFromNumberAccessor extends NumberAccessor {
     private final Calendar localCalendar;
+    private final int precision;
 
-    TimestampFromNumberAccessor(Getter getter, Calendar localCalendar) {
+    TimestampFromNumberAccessor(Getter getter, Calendar localCalendar, int 
precision) {
       super(getter, 0);
       this.localCalendar = localCalendar;
+      this.precision = precision;
     }
 
     @Override public Object getObject() throws SQLException {
@@ -1052,7 +1056,7 @@ public abstract class AbstractCursor implements Cursor {
       if (v == null) {
         return null;
       }
-      return timestampAsString(v.longValue(), null);
+      return timestampAsString(v.longValue(), null, this.precision);
     }
 
     protected Number getNumber() throws SQLException {
@@ -1155,7 +1159,8 @@ public abstract class AbstractCursor implements Cursor {
         return null;
       }
       final int unix = DateTimeUtils.sqlTimeToUnixTime(time, localCalendar);
-      return timeAsString(unix, null);
+      // java.sql.Time only supports a precision of 0
+      return timeAsString(unix, null, 0);
     }
 
     @Override public long getLong() throws SQLException {
@@ -1178,10 +1183,12 @@ public abstract class AbstractCursor implements Cursor {
    */
   static class TimestampAccessor extends ObjectAccessor {
     private final Calendar localCalendar;
+    private final int precision;
 
-    TimestampAccessor(Getter getter, Calendar localCalendar) {
+    TimestampAccessor(Getter getter, Calendar localCalendar, int precision) {
       super(getter);
       this.localCalendar = localCalendar;
+      this.precision = precision;
     }
 
     @Override public Timestamp getTimestamp(Calendar calendar) throws 
SQLException {
@@ -1220,7 +1227,7 @@ public abstract class AbstractCursor implements Cursor {
       }
       final long unix =
           DateTimeUtils.sqlTimestampToUnixTimestamp(timestamp, localCalendar);
-      return timestampAsString(unix, null);
+      return timestampAsString(unix, null, this.precision);
     }
 
     @Override public long getLong() throws SQLException {
@@ -1241,11 +1248,13 @@ public abstract class AbstractCursor implements Cursor {
    */
   static class TimestampFromUtilDateAccessor extends ObjectAccessor {
     private final Calendar localCalendar;
+    private final int precision;
 
     TimestampFromUtilDateAccessor(Getter getter,
-        Calendar localCalendar) {
+        Calendar localCalendar, int precision) {
       super(getter);
       this.localCalendar = localCalendar;
+      this.precision = precision;
     }
 
     @Override public Timestamp getTimestamp(Calendar calendar) throws 
SQLException {
@@ -1282,7 +1291,7 @@ public abstract class AbstractCursor implements Cursor {
         return null;
       }
       final long unix = DateTimeUtils.utilDateToUnixTimestamp(date, 
localCalendar);
-      return timestampAsString(unix, null);
+      return timestampAsString(unix, null, this.precision);
     }
 
     @Override public long getLong() throws SQLException {
diff --git 
a/core/src/test/java/org/apache/calcite/avatica/util/TimeFromNumberAccessorTest.java
 
b/core/src/test/java/org/apache/calcite/avatica/util/TimeFromNumberAccessorTest.java
index 87f557dc8..efa7a8709 100644
--- 
a/core/src/test/java/org/apache/calcite/avatica/util/TimeFromNumberAccessorTest.java
+++ 
b/core/src/test/java/org/apache/calcite/avatica/util/TimeFromNumberAccessorTest.java
@@ -48,7 +48,7 @@ public class TimeFromNumberAccessorTest {
     final AbstractCursor.Getter getter = new LocalGetter();
     localCalendar = Calendar.getInstance(TimeZone.getDefault(), Locale.ROOT);
     instance = new AbstractCursor.TimeFromNumberAccessor(getter,
-        localCalendar);
+        localCalendar, 0);
   }
 
   /**
@@ -156,4 +156,26 @@ public class TimeFromNumberAccessorTest {
       return value == null;
     }
   }
+
+  /**
+   * Test case for <a 
href="https://issues.apache.org/jira/browse/CALCITE-6282";>[CALCITE-6282]
+   * Avatica ignores time precision when returning TIME results</a>. */
+  @Test public void testPrecision() throws SQLException {
+    final AbstractCursor.Getter getter = new AbstractCursor.Getter() {
+      @Override
+      public Object getObject() throws SQLException {
+        // This is the representation of TIME '12:42:25.34'
+        return 45745340;
+      }
+
+      @Override
+      public boolean wasNull() throws SQLException {
+        return false;
+      }
+    };
+    AbstractCursor.TimeFromNumberAccessor accessor = new 
AbstractCursor.TimeFromNumberAccessor(
+        getter, null, 2);
+    String string = accessor.getString();
+    assertThat(string, is("12:42:25.34"));
+  }
 }
diff --git 
a/core/src/test/java/org/apache/calcite/avatica/util/TimestampAccessorTest.java 
b/core/src/test/java/org/apache/calcite/avatica/util/TimestampAccessorTest.java
index 98d20c00f..573c59e6a 100644
--- 
a/core/src/test/java/org/apache/calcite/avatica/util/TimestampAccessorTest.java
+++ 
b/core/src/test/java/org/apache/calcite/avatica/util/TimestampAccessorTest.java
@@ -60,7 +60,7 @@ public class TimestampAccessorTest {
   @Before public void before() {
     final AbstractCursor.Getter getter = new LocalGetter();
     localCalendar = Calendar.getInstance(TimeZone.getDefault(), Locale.ROOT);
-    instance = new AbstractCursor.TimestampAccessor(getter, localCalendar);
+    instance = new AbstractCursor.TimestampAccessor(getter, localCalendar, 0);
   }
 
   /**
diff --git 
a/core/src/test/java/org/apache/calcite/avatica/util/TimestampFromNumberAccessorTest.java
 
b/core/src/test/java/org/apache/calcite/avatica/util/TimestampFromNumberAccessorTest.java
index d8fd819fb..8ca94ff8f 100644
--- 
a/core/src/test/java/org/apache/calcite/avatica/util/TimestampFromNumberAccessorTest.java
+++ 
b/core/src/test/java/org/apache/calcite/avatica/util/TimestampFromNumberAccessorTest.java
@@ -40,6 +40,10 @@ public class TimestampFromNumberAccessorTest {
   // UTC: 2014-09-30 15:28:27.356
   private static final long DST_INSTANT = 1412090907356L;
   private static final String DST_STRING = "2014-09-30 15:28:27";
+  // With precision 2
+  private static final String DST_STRING_2 = "2014-09-30 15:28:27.35";
+  // With precision 3
+  private static final String DST_STRING_3 = "2014-09-30 15:28:27.356";
 
   // UTC: 1500-04-30 12:00:00.123 (JULIAN CALENDAR)
   private static final long PRE_GREG_INSTANT = -14821444799877L;
@@ -56,7 +60,7 @@ public class TimestampFromNumberAccessorTest {
   @Before public void before() {
     final AbstractCursor.Getter getter = new LocalGetter();
     localCalendar = Calendar.getInstance(TimeZone.getDefault(), Locale.ROOT);
-    instance = new AbstractCursor.TimestampFromNumberAccessor(getter, 
localCalendar);
+    instance = new AbstractCursor.TimestampFromNumberAccessor(getter, 
localCalendar, 0);
   }
 
   /**
@@ -72,6 +76,31 @@ public class TimestampFromNumberAccessorTest {
         is(Timestamp.valueOf("1500-04-30 12:00:00")));
   }
 
+  /**
+   * Test case for <a 
href="https://issues.apache.org/jira/browse/CALCITE-6282";>
+   * [CALCITE-6282] Avatica ignores time precision when returning TIME 
results</a>. */
+  @Test public void testPrecision() throws SQLException {
+    final AbstractCursor.Getter getter = new AbstractCursor.Getter() {
+      @Override
+      public Object getObject() throws SQLException {
+        return DST_INSTANT;
+      }
+
+      @Override
+      public boolean wasNull() throws SQLException {
+        return false;
+      }
+    };
+    AbstractCursor.TimestampFromNumberAccessor accessor =
+        new AbstractCursor.TimestampFromNumberAccessor(getter, null, 2);
+    String string = accessor.getString();
+    assertThat(string, is(DST_STRING_2));
+    accessor = new AbstractCursor.TimestampFromNumberAccessor(
+        getter, null, 3);
+    string = accessor.getString();
+    assertThat(string, is(DST_STRING_3));
+  }
+
   /**
    * Test {@code getDate()} handles time zone conversions relative to the 
local calendar and not
    * UTC.
diff --git 
a/core/src/test/java/org/apache/calcite/avatica/util/TimestampFromUtilDateAccessorTest.java
 
b/core/src/test/java/org/apache/calcite/avatica/util/TimestampFromUtilDateAccessorTest.java
index bdc7db1fa..ec214bb70 100644
--- 
a/core/src/test/java/org/apache/calcite/avatica/util/TimestampFromUtilDateAccessorTest.java
+++ 
b/core/src/test/java/org/apache/calcite/avatica/util/TimestampFromUtilDateAccessorTest.java
@@ -61,7 +61,7 @@ public class TimestampFromUtilDateAccessorTest {
   @Before public void before() {
     final AbstractCursor.Getter getter = new LocalGetter();
     localCalendar = Calendar.getInstance(TimeZone.getDefault(), Locale.ROOT);
-    instance = new AbstractCursor.TimestampFromUtilDateAccessor(getter, 
localCalendar);
+    instance = new AbstractCursor.TimestampFromUtilDateAccessor(getter, 
localCalendar, 0);
   }
 
   /**

Reply via email to