Skip to content

Commit

Permalink
Add fix for null-valued TIMESTAMP
Browse files Browse the repository at this point in the history
  • Loading branch information
wnob committed Dec 21, 2023
1 parent 94614a9 commit d6aab6e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/main/java/net/starschema/clouddb/jdbc/DateTimeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ static Timestamp parseDateTime(String value, Calendar cal) throws SQLException {

/** Parse a BigQuery TIMESTAMP literal, represented as the number of seconds since epoch. */
static Timestamp parseTimestamp(String value) throws SQLException {
if (value == null) {
return null;
}
try {
// BigQuery TIMESTAMP has a string representation that looks like e.g. "1.288061375E9"
// for 2010-10-26 02:49:35 UTC.
Expand All @@ -119,6 +122,9 @@ static Timestamp parseTimestamp(String value) throws SQLException {
}

static String formatTimestamp(String rawString) throws SQLException {
if (rawString == null) {
return null;
}
Timestamp timestamp = parseTimestamp(rawString);
return DATETIME_FORMATTER.format(OffsetDateTime.ofInstant(timestamp.toInstant(), UTC_ZONE))
+ " UTC";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
Expand Down Expand Up @@ -796,6 +797,58 @@ public void testHandlesAllNullResponseFields() throws Exception {
throw new AssertionError("Expected graceful failure due to lack of job reference");
}

@Test
public void testHandlesNullTimeDateObjects() throws Exception {
this.NewConnection("&useLegacySql=false");
Statement stmt = BQForwardOnlyResultSetFunctionTest.con.createStatement(
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);

final String date = "2011-11-11";
final String time = "12:12:12";
final String dateTime = date + " " + time;
final String dateTimeWithT = date + "T" + time;
// The number of milliseconds between epoch and 2011-11-11 12:12:12 UTC+0.
final long millis = 1321013532000L;

String sql = "SELECT " +
"TIMESTAMP('" + dateTime + "') AS ts, " +
"DATETIME('" + dateTime + "') AS dt, " +
"DATE('" + date + "') AS d, " +
"TIME(12, 12, 12) AS t\n" +
"UNION ALL SELECT " +
"CASE WHEN 1 = 0 THEN TIMESTAMP('" + dateTime + "') ELSE NULL END, " +
"CASE WHEN 1 = 0 THEN DATETIME('" + dateTime + "') ELSE NULL END, " +
"CASE WHEN 1 = 0 THEN DATE('" + date + "') ELSE NULL END, " +
"CASE WHEN 1 = 0 THEN TIME(12, 12, 12) ELSE NULL END";

ResultSet results = stmt.executeQuery(sql);

// First row has all non-null objects.
Assertions.assertThat(results.next()).isTrue();
Assertions.assertThat(results.getObject("ts")).isEqualTo(Timestamp.from(Instant.ofEpochMilli(millis)));
Assertions.assertThat(results.getString("ts")).isEqualTo(dateTime + " UTC");
Assertions.assertThat(results.getObject("dt")).isEqualTo(Timestamp.valueOf(dateTime));
Assertions.assertThat(results.getString("dt")).isEqualTo(dateTimeWithT);
Assertions.assertThat(results.getObject("d")).isEqualTo(java.sql.Date.valueOf(date));
Assertions.assertThat(results.getString("d")).isEqualTo(date);
Assertions.assertThat(results.getObject("t")).isEqualTo(java.sql.Time.valueOf(time));
Assertions.assertThat(results.getString("t")).isEqualTo(time);

// Second row is all null.
Assertions.assertThat(results.next()).isTrue();
Assertions.assertThat(results.getObject("ts")).isNull();
Assertions.assertThat(results.getString("ts")).isNull();
Assertions.assertThat(results.getObject("dt")).isNull();
Assertions.assertThat(results.getString("dt")).isNull();
Assertions.assertThat(results.getObject("d")).isNull();
Assertions.assertThat(results.getString("d")).isNull();
Assertions.assertThat(results.getObject("t")).isNull();
Assertions.assertThat(results.getString("t")).isNull();

// Only two rows.
Assertions.assertThat(results.next()).isFalse();
}

@Test
public void testHandlesSomeNullResponseFields() throws Exception {
// Make sure we don't get any NPE's due to null values;
Expand Down

0 comments on commit d6aab6e

Please sign in to comment.