Skip to content

Commit

Permalink
SNOW-1636262: getDate triggers NPE with 3.18.0 (regression) (#1877)
Browse files Browse the repository at this point in the history
  • Loading branch information
sfc-gh-jszczerbinski authored Aug 29, 2024
1 parent 3ede535 commit 0b79dd9
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,22 +63,28 @@ public abstract class SnowflakeBaseResultSet implements ResultSet {
protected SnowflakeResultSetMetaDataV1 resultSetMetaData = null;
protected Map<String, Object> parameters = new HashMap<>();
private int fetchSize = 0;
protected SFBaseSession session = null;
protected SFBaseSession session;
private final SnowflakeResultSetSerializableV1 serializable;
private static final ObjectMapper OBJECT_MAPPER = ObjectMapperFactory.getObjectMapper();

SnowflakeBaseResultSet(Statement statement) throws SQLException {
this.statement = statement;
this.resultSetType = statement.getResultSetType();
this.resultSetConcurrency = statement.getResultSetConcurrency();
this.resultSetHoldability = statement.getResultSetHoldability();
this.session = maybeGetSession(statement);
this.serializable = null;
}

private static SFBaseSession maybeGetSession(Statement statement) {
try {
this.session = statement.unwrap(SnowflakeStatementV1.class).connection.getSFBaseSession();
return statement.unwrap(SnowflakeStatementV1.class).connection.getSFBaseSession();
} catch (SQLException e) {
// This exception shouldn't be hit. Statement class should be able to be unwrapped.
logger.error(
"Unable to unwrap SnowflakeStatementV1 class to retrieve session. Session is null.",
false);
this.session = null;
return null;
}
}

Expand All @@ -95,6 +101,8 @@ public SnowflakeBaseResultSet(SnowflakeResultSetSerializableV1 resultSetSerializ
this.resultSetType = resultSetSerializable.getResultSetType();
this.resultSetConcurrency = resultSetSerializable.getResultSetConcurrency();
this.resultSetHoldability = resultSetSerializable.getResultSetHoldability();
this.session = null;
this.serializable = resultSetSerializable;
}

/**
Expand All @@ -107,6 +115,8 @@ protected SnowflakeBaseResultSet() throws SQLException {
this.resultSetConcurrency = 0;
this.resultSetHoldability = 0;
this.statement = new SnowflakeStatementV1.NoOpSnowflakeStatementV1();
this.session = null;
this.serializable = null;
}

@Override
Expand All @@ -131,12 +141,22 @@ protected void raiseSQLExceptionIfResultSetIsClosed() throws SQLException {

public abstract Date getDate(int columnIndex, TimeZone tz) throws SQLException;

private boolean getGetDateUseNullTimezone() {
if (this.session != null) {
return this.session.getGetDateUseNullTimezone();
}

if (this.serializable != null) {
return this.serializable.getGetDateUseNullTimezone();
}

return false;
}

@Override
public Date getDate(int columnIndex) throws SQLException {
raiseSQLExceptionIfResultSetIsClosed();
return getDate(
columnIndex,
this.session.getGetDateUseNullTimezone() ? (TimeZone) null : TimeZone.getDefault());
return getDate(columnIndex, getGetDateUseNullTimezone() ? null : TimeZone.getDefault());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@ public String toString() {
int resultSetType;
int resultSetConcurrency;
int resultSetHoldability;
boolean treatNTZAsUTC;
boolean formatDateWithTimezone;
boolean useSessionTimezone;
boolean getDateUseNullTimezone;

// Below are some metadata fields parsed from the result JSON node
String queryId;
Expand All @@ -173,9 +177,6 @@ public String toString() {
long sendResultTime;
List<MetaDataOfBinds> metaDataOfBinds = new ArrayList<>();
QueryResultFormat queryResultFormat;
boolean treatNTZAsUTC;
boolean formatDateWithTimezone;
boolean useSessionTimezone;
int sessionClientMemoryLimit;

// Below fields are transient, they are generated from parameters
Expand Down Expand Up @@ -235,6 +236,7 @@ private SnowflakeResultSetSerializableV1(SnowflakeResultSetSerializableV1 toCopy
this.treatNTZAsUTC = toCopy.treatNTZAsUTC;
this.formatDateWithTimezone = toCopy.formatDateWithTimezone;
this.useSessionTimezone = toCopy.useSessionTimezone;
this.getDateUseNullTimezone = toCopy.getDateUseNullTimezone;

// Below are some metadata fields parsed from the result JSON node
this.queryId = toCopy.queryId;
Expand Down Expand Up @@ -438,6 +440,7 @@ protected SnowflakeResultSetSerializableV1(
this.treatNTZAsUTC = sfSession.getTreatNTZAsUTC();
this.formatDateWithTimezone = sfSession.getFormatDateWithTimezone();
this.useSessionTimezone = sfSession.getUseSessionTimezone();
this.getDateUseNullTimezone = sfSession.getGetDateUseNullTimezone();

// setup transient fields from parameter
this.setupFieldsFromParameters();
Expand Down Expand Up @@ -701,6 +704,10 @@ public boolean getUseSessionTimezone() {
return useSessionTimezone;
}

public boolean getGetDateUseNullTimezone() {
return getDateUseNullTimezone;
}

public Optional<SFBaseSession> getSession() {
return possibleSession;
}
Expand Down
27 changes: 27 additions & 0 deletions src/test/java/net/snowflake/client/jdbc/ConnectionIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,11 @@
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
Expand Down Expand Up @@ -800,6 +803,30 @@ public void testStatementsAndResultSetsClosedByConnection() throws SQLException
assertTrue(rs3.isClosed());
}

@Test
public void testReadDateAfterSplittingResultSet() throws Exception {
Connection conn = getConnection();
try (Statement statement = conn.createStatement()) {
statement.execute("create or replace table table_with_date (int_c int, date_c date)");
statement.execute("insert into table_with_date values (1, '2015-10-25')");

try (ResultSet rs = statement.executeQuery("select * from table_with_date")) {
final SnowflakeResultSet resultSet = rs.unwrap(SnowflakeResultSet.class);
final long arbitrarySizeInBytes = 1024;
final List<SnowflakeResultSetSerializable> serializables =
resultSet.getResultSetSerializables(arbitrarySizeInBytes);
final ArrayList<Date> dates = new ArrayList<>();
for (SnowflakeResultSetSerializable s : serializables) {
ResultSet srs = s.getResultSet();
srs.next();
dates.add(srs.getDate(2));
}
assertEquals(1, dates.size());
assertEquals("2015-10-25", dates.get(0).toString());
}
}
}

@Test
public void testResultSetsClosedByStatement() throws SQLException {
Connection connection = getConnection();
Expand Down

0 comments on commit 0b79dd9

Please sign in to comment.