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);
}
/**