Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNOW-1636262: getDate triggers NPE with 3.18.0 (regression) #1877

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
sfc-gh-pmotacki marked this conversation as resolved.
Show resolved Hide resolved

// 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;
sfc-gh-dheyman marked this conversation as resolved.
Show resolved Hide resolved
}

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
Loading