From 6858b613455a8624092b1007bb198c55aad54fbb Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Thu, 7 May 2026 15:54:11 -0400 Subject: [PATCH 1/4] chore(bqjdbc): suppress deprecation warnings --- .../cloud/bigquery/jdbc/BigQueryBaseResultSet.java | 8 ++++++++ .../cloud/bigquery/jdbc/BigQueryCallableStatement.java | 2 ++ .../cloud/bigquery/jdbc/BigQueryPreparedStatement.java | 2 ++ .../bigquery/jdbc/BigQueryTypeCoercionUtility.java | 10 +++++++++- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryBaseResultSet.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryBaseResultSet.java index 0e72a5fccf71..15397aca93f7 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryBaseResultSet.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryBaseResultSet.java @@ -351,6 +351,8 @@ public double getDouble(int columnIndex) throws SQLException { } @Override + @Deprecated + @SuppressWarnings("deprecation") public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { LOG.finest("++enter++"); try { @@ -470,6 +472,8 @@ public InputStream getAsciiStream(int columnIndex) throws SQLException { } @Override + @Deprecated + @SuppressWarnings("deprecation") public InputStream getUnicodeStream(int columnIndex) throws SQLException { LOG.finest("++enter++"); return getInputStream(getString(columnIndex), StandardCharsets.UTF_16LE); @@ -567,6 +571,8 @@ public double getDouble(String columnLabel) throws SQLException { } @Override + @Deprecated + @SuppressWarnings("deprecation") public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { return getBigDecimal(getColumnIndex(columnLabel), scale); } @@ -597,6 +603,8 @@ public InputStream getAsciiStream(String columnLabel) throws SQLException { } @Override + @Deprecated + @SuppressWarnings("deprecation") public InputStream getUnicodeStream(String columnLabel) throws SQLException { return getUnicodeStream(getColumnIndex(columnLabel)); } diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatement.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatement.java index 4c5d6ac3bbcd..260c35f8af1f 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatement.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryCallableStatement.java @@ -117,6 +117,8 @@ public BigDecimal getBigDecimal(String arg0) throws SQLException { } @Override + @Deprecated + @SuppressWarnings("deprecation") public BigDecimal getBigDecimal(int arg0, int arg1) throws SQLException { LOG.finest("++enter++"); return getBigDecimal(arg0); diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java index 356578e8dd27..f02227e0edc3 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java @@ -233,6 +233,8 @@ public void setAsciiStream(int parameterIndex, InputStream x, int length) { } @Override + @Deprecated + @SuppressWarnings("deprecation") public void setUnicodeStream(int parameterIndex, InputStream x, int length) { // TODO :NOT IMPLEMENTED } diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java index ec1ec140975a..b4de2eb87467 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java @@ -205,7 +205,15 @@ public Time coerce(Long value) { // Note: BQ Time has a precision of up to six fractional digits (microsecond precision) // but java.sql.Time do not. So data after seconds is not returned. - return new Time(HH, MM, SS); + // Using Calendar for timezone-safe date rollover arithmetic instead of the deprecated Time + // constructor. + java.util.Calendar cal = java.util.Calendar.getInstance(); + cal.clear(); + cal.set(1970, 0, 1, 0, 0, 0); + cal.add(java.util.Calendar.HOUR, HH); + cal.add(java.util.Calendar.MINUTE, MM); + cal.add(java.util.Calendar.SECOND, SS); + return new Time(cal.getTimeInMillis()); } } From e20c59e9331b6ff29f667c0431f8cf23263043aa Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Thu, 7 May 2026 16:17:36 -0400 Subject: [PATCH 2/4] fix(bqjdbc): fix Log to java.sql.Time coercion --- .../jdbc/BigQueryTypeCoercionUtility.java | 22 +++++-------------- ...FormatTypeBigQueryCoercionUtilityTest.java | 2 +- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java index b4de2eb87467..60ed2c35bb6b 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java @@ -198,22 +198,12 @@ private static class LongToTime implements BigQueryCoercion { @Override public Time coerce(Long value) { - - int HH = (int) TimeUnit.MICROSECONDS.toHours(value); - int MM = (int) (TimeUnit.MICROSECONDS.toMinutes(value) % 60); - int SS = (int) (TimeUnit.MICROSECONDS.toSeconds(value) % 60); - - // Note: BQ Time has a precision of up to six fractional digits (microsecond precision) - // but java.sql.Time do not. So data after seconds is not returned. - // Using Calendar for timezone-safe date rollover arithmetic instead of the deprecated Time - // constructor. - java.util.Calendar cal = java.util.Calendar.getInstance(); - cal.clear(); - cal.set(1970, 0, 1, 0, 0, 0); - cal.add(java.util.Calendar.HOUR, HH); - cal.add(java.util.Calendar.MINUTE, MM); - cal.add(java.util.Calendar.SECOND, SS); - return new Time(cal.getTimeInMillis()); + // Convert UTC epoch microseconds to Instant + Instant instant = Instant.ofEpochMilli(value / 1000); + // Convert to LocalTime using the system default timezone to ensure correct wall-clock time + LocalTime localTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).toLocalTime(); + // Return java.sql.Time with date component set to 1970-01-01 as mandated by JDBC spec + return Time.valueOf(localTime); } } diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/ArrowFormatTypeBigQueryCoercionUtilityTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/ArrowFormatTypeBigQueryCoercionUtilityTest.java index 627006988bce..e396a79d64f8 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/ArrowFormatTypeBigQueryCoercionUtilityTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/ArrowFormatTypeBigQueryCoercionUtilityTest.java @@ -165,7 +165,7 @@ public void nullToTime() { @Test public void longToTime() { assertThat(INSTANCE.coerceTo(Time.class, 1408452095220000L)) - .isEqualTo(new Time(1408452095000L)); + .isEqualTo(Time.valueOf(java.time.LocalTime.of(12, 41, 35))); } @Test From 1c7cc0c3009d0695284bac1db991267c0c2bf28f Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Thu, 7 May 2026 17:15:13 -0400 Subject: [PATCH 3/4] fix coercions --- .../jdbc/BigQueryTypeCoercionUtility.java | 28 +++++++++---------- ...FormatTypeBigQueryCoercionUtilityTest.java | 2 +- .../BigQueryArrowArrayOfPrimitivesTest.java | 16 +++++++---- .../jdbc/BigQueryArrowStructTest.java | 14 ++++++++-- ...dValueTypeBigQueryCoercionUtilityTest.java | 12 ++++---- 5 files changed, 41 insertions(+), 31 deletions(-) diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java index 60ed2c35bb6b..3d773c7c9514 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java @@ -30,7 +30,6 @@ import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Period; -import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; @@ -198,12 +197,10 @@ private static class LongToTime implements BigQueryCoercion { @Override public Time coerce(Long value) { - // Convert UTC epoch microseconds to Instant - Instant instant = Instant.ofEpochMilli(value / 1000); - // Convert to LocalTime using the system default timezone to ensure correct wall-clock time - LocalTime localTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).toLocalTime(); - // Return java.sql.Time with date component set to 1970-01-01 as mandated by JDBC spec - return Time.valueOf(localTime); + // Note: BQ Time has a precision of up to six fractional digits (microsecond precision) + // but java.sql.Time only supports up to millisecond precision. So data after milliseconds is + // truncated. + return new Time(value / 1000); } } @@ -213,9 +210,8 @@ private static class LongToTimestamp implements BigQueryCoercion data() { timeZoneRule.enforce(); LocalDateTime aTimeStamp = LocalDateTime.of(2023, MARCH, 30, 11, 14, 19, 820227000); LocalDate aDate = LocalDate.of(2023, MARCH, 30); - LocalTime aTime = LocalTime.of(11, 14, 19, 820227); + LocalTime aTime = LocalTime.of(11, 14, 19, 820227000); return Arrays.asList( new Object[][] { { @@ -176,10 +176,16 @@ STRING, new Text("one"), new Text("two"), new Text("three"), new Text("four")), Long.valueOf("40461820227"), Long.valueOf("40462820227")), new Time[] { - Time.valueOf(aTime), - Time.valueOf(aTime.plusSeconds(1)), - Time.valueOf(aTime.plusSeconds(2)), - Time.valueOf(aTime.plusSeconds(3)) + new Time(java.util.concurrent.TimeUnit.NANOSECONDS.toMillis(aTime.toNanoOfDay())), + new Time( + java.util.concurrent.TimeUnit.NANOSECONDS.toMillis( + aTime.plusSeconds(1).toNanoOfDay())), + new Time( + java.util.concurrent.TimeUnit.NANOSECONDS.toMillis( + aTime.plusSeconds(2).toNanoOfDay())), + new Time( + java.util.concurrent.TimeUnit.NANOSECONDS.toMillis( + aTime.plusSeconds(3).toNanoOfDay())) }, Types.TIME }, diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryArrowStructTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryArrowStructTest.java index 3f6b528c87db..095435b57fa6 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryArrowStructTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryArrowStructTest.java @@ -106,7 +106,9 @@ public void structOfPrimitives() throws SQLException { "one", Timestamp.valueOf(LocalDateTime.of(2023, MARCH, 30, 11, 14, 19, 820227000)), Date.valueOf(LocalDate.of(2023, MARCH, 30)), - Time.valueOf(LocalTime.of(11, 14, 19, 820227)), + new Time( + java.util.concurrent.TimeUnit.NANOSECONDS.toMillis( + LocalTime.of(11, 14, 19, 820227000).toNanoOfDay())), Timestamp.valueOf("2023-03-30 11:14:19.820227"), "POINT(-122 47)", "one".getBytes()) @@ -117,7 +119,7 @@ public void structOfPrimitives() throws SQLException { public void structOfArrays() throws SQLException { LocalDateTime aTimeStamp = LocalDateTime.of(2023, MARCH, 30, 11, 14, 19, 820227000); LocalDate aDate = LocalDate.of(2023, MARCH, 30); - LocalTime aTime = LocalTime.of(11, 14, 19, 820227); + LocalTime aTime = LocalTime.of(11, 14, 19, 820227000); List>> schemaAndValues = Arrays.asList( arrowArraySchemaAndValue(INT64, 10L, 20L), @@ -165,7 +167,13 @@ GEOGRAPHY, new Text("POINT(-122 47)"), new Text("POINT(-122 48)")), assertThat(((Array) attributes[7]).getArray()) .isEqualTo(new Date[] {Date.valueOf(aDate), Date.valueOf(aDate.plusDays(1))}); assertThat(((Array) attributes[8]).getArray()) - .isEqualTo(new Time[] {Time.valueOf(aTime), Time.valueOf(aTime.plusSeconds(1))}); + .isEqualTo( + new Time[] { + new Time(java.util.concurrent.TimeUnit.NANOSECONDS.toMillis(aTime.toNanoOfDay())), + new Time( + java.util.concurrent.TimeUnit.NANOSECONDS.toMillis( + aTime.plusSeconds(1).toNanoOfDay())) + }); assertThat(((Array) attributes[9]).getArray()) // DATETIME .isEqualTo( new Timestamp[] { diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/FieldValueTypeBigQueryCoercionUtilityTest.java b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/FieldValueTypeBigQueryCoercionUtilityTest.java index b5df1e1fc58c..7450a1a52798 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/FieldValueTypeBigQueryCoercionUtilityTest.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/FieldValueTypeBigQueryCoercionUtilityTest.java @@ -36,9 +36,7 @@ import java.sql.Timestamp; import java.time.Instant; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; @@ -299,9 +297,8 @@ public void fieldValueToBytesArrayWhenInnerValueIsNull() { @Test public void fieldValueToTimestamp() { Instant instant = Instant.EPOCH.plus(TIMESTAMP_VALUE.getTimestampValue(), ChronoUnit.MICROS); - LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("UTC")); assertThat(INSTANCE.coerceTo(Timestamp.class, TIMESTAMP_VALUE)) - .isEqualTo(Timestamp.valueOf(localDateTime)); + .isEqualTo(Timestamp.from(instant)); } @Test @@ -317,11 +314,12 @@ public void fieldValueToTimestampWhenInnerValueIsNull() { @Test public void fieldValueToTime() { LocalTime expectedTime = LocalTime.of(23, 59, 59); - assertThat(INSTANCE.coerceTo(Time.class, TIME_VALUE)) - .isEqualTo(new Time(TimeUnit.NANOSECONDS.toMillis(expectedTime.toNanoOfDay()))); + assertThat(INSTANCE.coerceTo(Time.class, TIME_VALUE)).isEqualTo(Time.valueOf(expectedTime)); LocalTime expectedTimeWithNanos = LocalTime.parse("23:59:59.99999"); + long millisOfDay = TimeUnit.NANOSECONDS.toMillis(expectedTimeWithNanos.toNanoOfDay()); + long localMillis = millisOfDay - java.util.TimeZone.getDefault().getOffset(millisOfDay); assertThat(INSTANCE.coerceTo(Time.class, TIME_WITH_NANOSECOND_VALUE)) - .isEqualTo(new Time(TimeUnit.NANOSECONDS.toMillis(expectedTimeWithNanos.toNanoOfDay()))); + .isEqualTo(new Time(localMillis)); } @Test From ba2ae85bc619c2e4993b0735ae9965c1031175d5 Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Fri, 8 May 2026 17:39:02 -0400 Subject: [PATCH 4/4] address comments --- .../google-cloud-bigquery-jdbc/.gitignore | 1 + .../jdbc/BigQueryTypeCoercionUtility.java | 8 +++-- .../cloud/bigquery/jdbc/TimeZoneCache.java | 33 +++++++++++++++++++ ...FormatTypeBigQueryCoercionUtilityTest.java | 24 ++++++++++++-- ...dValueTypeBigQueryCoercionUtilityTest.java | 29 +++++++++++++--- .../bigquery/jdbc/rules/TimeZoneRule.java | 5 +++ 6 files changed, 90 insertions(+), 10 deletions(-) create mode 100644 java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/TimeZoneCache.java diff --git a/java-bigquery/google-cloud-bigquery-jdbc/.gitignore b/java-bigquery/google-cloud-bigquery-jdbc/.gitignore index 2c4fba513e11..40a3476b598a 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/.gitignore +++ b/java-bigquery/google-cloud-bigquery-jdbc/.gitignore @@ -2,6 +2,7 @@ drivers/** target-it/** *logs*/** **/ITBigQueryJDBCLocalTest.java +**/BigQueryStatementE2EBenchmark.java tools/**/*.class tools/**/*.jfr \ No newline at end of file diff --git a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java index 3d773c7c9514..ae51736473dd 100644 --- a/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java +++ b/java-bigquery/google-cloud-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryTypeCoercionUtility.java @@ -200,7 +200,9 @@ public Time coerce(Long value) { // Note: BQ Time has a precision of up to six fractional digits (microsecond precision) // but java.sql.Time only supports up to millisecond precision. So data after milliseconds is // truncated. - return new Time(value / 1000); + long millisOfDay = value / 1000; + long localMillis = TimeZoneCache.getLocalMillis(millisOfDay); + return new Time(localMillis); } } @@ -209,7 +211,7 @@ private static class LongToTimestamp implements BigQueryCoercion