diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 199e5cedd..f3e0c7747 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,59 +1,59 @@
**JDBC Driver 3.15.0**
-- \||Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \||Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.14.5**
-- \||Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \||Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.14.4**
-- \||Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \||Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.14.3**
-- \||Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \||Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.14.2**
-- \||Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \||Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.14.1**
-- \||Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \||Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.14.0**
-- \||Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \||Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.13.33**
-- \|| Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \|| Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.13.32**
-- \|| Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \|| Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.13.31**
-- \|| Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \|| Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.13.30**
-- \|| Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \|| Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.13.29**
-- \|| Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \|| Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.13.28**
-- \|| Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \|| Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.13.27**
-- \|| Please Refer to Release Notes at https://docs.snowflake.com/en/release-notes/clients-drivers/jdbc
+- \|| Please Refer to Release Notes at https://community.snowflake.com/s/article/JDBC-Driver-Release-Notes
**JDBC Driver 3.13.26**
diff --git a/parent-pom.xml b/parent-pom.xml
index ff8ee40f9..cceedf9cd 100644
--- a/parent-pom.xml
+++ b/parent-pom.xml
@@ -38,7 +38,6 @@
1.5.4
0.9.5.4
2.22.0
- 1.19.0
2.21.0
2.22.6
2.10.1
@@ -162,11 +161,6 @@
proto-google-common-protos
${google.api.grpc.version}
-
- com.google.auth
- google-auth-library-oauth2-http
- ${google.auth.library.oauth2.http.version}
-
com.google.cloud
google-cloud-core
@@ -520,10 +514,6 @@
com.google.api
gax
-
- com.google.auth
- google-auth-library-oauth2-http
-
com.google.cloud
google-cloud-core
diff --git a/src/main/java/net/snowflake/client/core/JsonSqlInput.java b/src/main/java/net/snowflake/client/core/JsonSqlInput.java
index 0ae79096a..2430d0c7f 100644
--- a/src/main/java/net/snowflake/client/core/JsonSqlInput.java
+++ b/src/main/java/net/snowflake/client/core/JsonSqlInput.java
@@ -190,9 +190,11 @@ public Timestamp readTimestamp(TimeZone tz) throws SQLException {
int columnType = ColumnTypeHelper.getColumnType(fieldMetadata.getType(), session);
int columnSubType = fieldMetadata.getType();
int scale = fieldMetadata.getScale();
+
Timestamp result =
SqlInputTimestampUtil.getTimestampFromType(
columnSubType, (String) value, session, sessionTimeZone, tz);
+
if (result != null) {
return result;
}
diff --git a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java
index 5bb67919e..852e187b4 100644
--- a/src/main/java/net/snowflake/client/core/SFArrowResultSet.java
+++ b/src/main/java/net/snowflake/client/core/SFArrowResultSet.java
@@ -13,7 +13,6 @@
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
-import java.sql.Array;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.SQLInput;
diff --git a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java
index 24756bbc7..0a0dd35a2 100644
--- a/src/main/java/net/snowflake/client/core/SFBaseResultSet.java
+++ b/src/main/java/net/snowflake/client/core/SFBaseResultSet.java
@@ -11,7 +11,6 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import java.math.BigDecimal;
-import java.sql.Array;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.SQLInput;
diff --git a/src/main/java/net/snowflake/client/core/SFBaseSession.java b/src/main/java/net/snowflake/client/core/SFBaseSession.java
index b0da3e9b4..d0bfeda9d 100644
--- a/src/main/java/net/snowflake/client/core/SFBaseSession.java
+++ b/src/main/java/net/snowflake/client/core/SFBaseSession.java
@@ -137,9 +137,6 @@ public abstract class SFBaseSession {
// we need to allow for it to maintain backwards compatibility.
private boolean enablePatternSearch = true;
- /** Disable lookup for default credentials by GCS library */
- private boolean disableGcsDefaultCredentials = false;
-
private Map commonParameters;
private boolean isJdbcArrowTreatDecimalAsInt = true;
@@ -748,14 +745,6 @@ public void setEnablePatternSearch(boolean enablePatternSearch) {
this.enablePatternSearch = enablePatternSearch;
}
- public boolean getDisableGcsDefaultCredentials() {
- return disableGcsDefaultCredentials;
- }
-
- public void setDisableGcsDefaultCredentials(boolean disableGcsDefaultCredentials) {
- this.disableGcsDefaultCredentials = disableGcsDefaultCredentials;
- }
-
public int getClientResultChunkSize() {
return clientResultChunkSize;
}
diff --git a/src/main/java/net/snowflake/client/core/SFJsonResultSet.java b/src/main/java/net/snowflake/client/core/SFJsonResultSet.java
index 181492294..48bb16e33 100644
--- a/src/main/java/net/snowflake/client/core/SFJsonResultSet.java
+++ b/src/main/java/net/snowflake/client/core/SFJsonResultSet.java
@@ -7,7 +7,6 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import java.math.BigDecimal;
-import java.sql.Array;
import java.sql.Date;
import java.sql.SQLInput;
import java.sql.Time;
@@ -88,6 +87,7 @@ public Object getObject(int columnIndex) throws SFException {
} else {
throw new SFException(ErrorCode.FEATURE_UNSUPPORTED, "data type: " + type);
}
+
case Types.ARRAY:
if (StructureTypeHelper.isStructureTypeEnabled()) {
return getArray(columnIndex);
diff --git a/src/main/java/net/snowflake/client/core/SFResultSet.java b/src/main/java/net/snowflake/client/core/SFResultSet.java
index b7698cf5d..77f30ddd7 100644
--- a/src/main/java/net/snowflake/client/core/SFResultSet.java
+++ b/src/main/java/net/snowflake/client/core/SFResultSet.java
@@ -155,7 +155,22 @@ public SFResultSet(
Telemetry telemetryClient,
boolean sortResult)
throws SQLException {
- super(resultSetSerializable.getTimeZone(), new Converters(session, resultSetSerializable));
+ super(
+ resultSetSerializable.getTimeZone(),
+ new Converters(
+ resultSetSerializable.getTimeZone(),
+ session,
+ resultSetSerializable.getResultVersion(),
+ resultSetSerializable.isHonorClientTZForTimestampNTZ(),
+ resultSetSerializable.getTreatNTZAsUTC(),
+ resultSetSerializable.getUseSessionTimezone(),
+ resultSetSerializable.getFormatDateWithTimeZone(),
+ resultSetSerializable.getBinaryFormatter(),
+ resultSetSerializable.getDateFormatter(),
+ resultSetSerializable.getTimeFormatter(),
+ resultSetSerializable.getTimestampNTZFormatter(),
+ resultSetSerializable.getTimestampLTZFormatter(),
+ resultSetSerializable.getTimestampTZFormatter()));
this.resultSetSerializable = resultSetSerializable;
this.columnCount = 0;
this.sortResult = sortResult;
diff --git a/src/main/java/net/snowflake/client/core/SFResultSetMetaData.java b/src/main/java/net/snowflake/client/core/SFResultSetMetaData.java
index ce129788b..dfb621400 100644
--- a/src/main/java/net/snowflake/client/core/SFResultSetMetaData.java
+++ b/src/main/java/net/snowflake/client/core/SFResultSetMetaData.java
@@ -473,8 +473,7 @@ public List getIsAutoIncrementList() {
return isAutoIncrementList;
}
- @SnowflakeJdbcInternalApi
- public List getColumnMetadata() {
+ List getColumnMetadata() {
return columnMetadata;
}
}
diff --git a/src/main/java/net/snowflake/client/core/SFSession.java b/src/main/java/net/snowflake/client/core/SFSession.java
index d7ee69a07..a0c25c213 100644
--- a/src/main/java/net/snowflake/client/core/SFSession.java
+++ b/src/main/java/net/snowflake/client/core/SFSession.java
@@ -469,11 +469,6 @@ public void addSFSessionProperty(String propertyName, Object propertyValue) thro
setEnablePatternSearch(getBooleanValue(propertyValue));
}
break;
- case DISABLE_GCS_DEFAULT_CREDENTIALS:
- if (propertyValue != null) {
- setDisableGcsDefaultCredentials(getBooleanValue(propertyValue));
- }
- break;
case JDBC_ARROW_TREAT_DECIMAL_AS_INT:
if (propertyValue != null) {
diff --git a/src/main/java/net/snowflake/client/core/SessionUtil.java b/src/main/java/net/snowflake/client/core/SessionUtil.java
index 9a51cd8ae..88020f6f0 100644
--- a/src/main/java/net/snowflake/client/core/SessionUtil.java
+++ b/src/main/java/net/snowflake/client/core/SessionUtil.java
@@ -401,7 +401,21 @@ private static SFLoginOutput newSession(
}
} else if (authenticatorType == ClientAuthnDTO.AuthenticatorType.OKTA) {
// okta authenticator v1
- tokenOrSamlResponse = getSamlResponseUsingOkta(loginInput);
+ while (true) {
+ try {
+ tokenOrSamlResponse = getSamlResponseUsingOkta(loginInput);
+ } catch (SnowflakeSQLException ex) {
+ // This error gets thrown if the okta request encountered a retry-able error that
+ // requires getting a new one-time token.
+ if (ex.getErrorCode() == ErrorCode.AUTHENTICATOR_REQUEST_TIMEOUT.getMessageCode()) {
+ logger.debug("Failed to get Okta SAML response. Retrying.");
+ continue;
+ } else {
+ throw ex;
+ }
+ }
+ break;
+ }
} else if (authenticatorType == ClientAuthnDTO.AuthenticatorType.SNOWFLAKE_JWT) {
SessionUtilKeyPair s =
new SessionUtilKeyPair(
@@ -651,16 +665,31 @@ private static SFLoginOutput newSession(
loginInput.getHttpClientSettingsKey());
} catch (SnowflakeSQLException ex) {
if (ex.getErrorCode() == ErrorCode.AUTHENTICATOR_REQUEST_TIMEOUT.getMessageCode()) {
- if (authenticatorType == ClientAuthnDTO.AuthenticatorType.SNOWFLAKE_JWT) {
- SessionUtilKeyPair s =
- new SessionUtilKeyPair(
- loginInput.getPrivateKey(),
- loginInput.getPrivateKeyFile(),
- loginInput.getPrivateKeyFilePwd(),
- loginInput.getAccountName(),
- loginInput.getUserName());
-
- data.put(ClientAuthnParameter.TOKEN.name(), s.issueJwtToken());
+ if (authenticatorType == ClientAuthnDTO.AuthenticatorType.SNOWFLAKE_JWT
+ || authenticatorType == ClientAuthnDTO.AuthenticatorType.OKTA) {
+
+ if (authenticatorType == ClientAuthnDTO.AuthenticatorType.SNOWFLAKE_JWT) {
+ SessionUtilKeyPair s =
+ new SessionUtilKeyPair(
+ loginInput.getPrivateKey(),
+ loginInput.getPrivateKeyFile(),
+ loginInput.getPrivateKeyFilePwd(),
+ loginInput.getAccountName(),
+ loginInput.getUserName());
+
+ data.put(ClientAuthnParameter.TOKEN.name(), s.issueJwtToken());
+ } else if (authenticatorType == ClientAuthnDTO.AuthenticatorType.OKTA) {
+ logger.debug("Retrieve new token for Okta authentication.");
+ // If we need to retry, we need to get a new Okta token
+ tokenOrSamlResponse = getSamlResponseUsingOkta(loginInput);
+ data.put(ClientAuthnParameter.RAW_SAML_RESPONSE.name(), tokenOrSamlResponse);
+ authnData.setData(data);
+ String updatedJson = mapper.writeValueAsString(authnData);
+
+ StringEntity updatedInput = new StringEntity(updatedJson, StandardCharsets.UTF_8);
+ updatedInput.setContentType("application/json");
+ postRequest.setEntity(updatedInput);
+ }
long elapsedSeconds = ex.getElapsedSeconds();
@@ -690,7 +719,8 @@ private static SFLoginOutput newSession(
}
}
- // JWT renew should not count as a retry, so we pass back the current retry count.
+ // JWT or Okta renew should not count as a retry, so we pass back the current retry
+ // count.
retryCount = ex.getRetryCount();
continue;
diff --git a/src/main/java/net/snowflake/client/core/SfSqlArray.java b/src/main/java/net/snowflake/client/core/SfSqlArray.java
deleted file mode 100644
index 83270796a..000000000
--- a/src/main/java/net/snowflake/client/core/SfSqlArray.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package net.snowflake.client.core;
-
-import java.sql.Array;
-import java.sql.JDBCType;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
-import java.util.Map;
-
-@SnowflakeJdbcInternalApi
-public class SfSqlArray implements Array {
-
- private int baseType;
- private Object elements;
-
- public SfSqlArray(int baseType, Object elements) {
- this.baseType = baseType;
- this.elements = elements;
- }
-
- @Override
- public String getBaseTypeName() throws SQLException {
- return JDBCType.valueOf(baseType).getName();
- }
-
- @Override
- public int getBaseType() throws SQLException {
- return baseType;
- }
-
- @Override
- public Object getArray() throws SQLException {
- return elements;
- }
-
- @Override
- public Object getArray(Map> map) throws SQLException {
- throw new SQLFeatureNotSupportedException("getArray(Map> map)");
- }
-
- @Override
- public Object getArray(long index, int count) throws SQLException {
- throw new SQLFeatureNotSupportedException("getArray(long index, int count)");
- }
-
- @Override
- public Object getArray(long index, int count, Map> map) throws SQLException {
- throw new SQLFeatureNotSupportedException(
- "getArray(long index, int count, Map> map)");
- }
-
- @Override
- public ResultSet getResultSet() throws SQLException {
- throw new SQLFeatureNotSupportedException(
- "getArray(long index, int count, Map> map)");
- }
-
- @Override
- public ResultSet getResultSet(Map> map) throws SQLException {
- throw new SQLFeatureNotSupportedException("getResultSet(Map> map)");
- }
-
- @Override
- public ResultSet getResultSet(long index, int count) throws SQLException {
- throw new SQLFeatureNotSupportedException("getResultSet(long index, int count)");
- }
-
- @Override
- public ResultSet getResultSet(long index, int count, Map> map)
- throws SQLException {
- throw new SQLFeatureNotSupportedException(
- "getResultSet(long index, int count, Map> map)");
- }
-
- @Override
- public void free() throws SQLException {}
-}
diff --git a/src/main/java/net/snowflake/client/core/json/Converters.java b/src/main/java/net/snowflake/client/core/json/Converters.java
index a2f911b39..0fa0c3284 100644
--- a/src/main/java/net/snowflake/client/core/json/Converters.java
+++ b/src/main/java/net/snowflake/client/core/json/Converters.java
@@ -20,7 +20,6 @@
import net.snowflake.client.jdbc.SnowflakeResultSetSerializableV1;
import net.snowflake.client.util.Converter;
import net.snowflake.common.core.SFBinaryFormat;
-import net.snowflake.common.core.SFTimestamp;
import net.snowflake.common.core.SnowflakeDateTimeFormat;
public class Converters {
@@ -79,24 +78,6 @@ public Converters(
formatDateWithTimeZone);
}
- @SnowflakeJdbcInternalApi
- public Converters(SFBaseSession session, SnowflakeResultSetSerializableV1 resultSetSerializable) {
- this(
- resultSetSerializable.getTimeZone(),
- session,
- resultSetSerializable.getResultVersion(),
- resultSetSerializable.isHonorClientTZForTimestampNTZ(),
- resultSetSerializable.getTreatNTZAsUTC(),
- resultSetSerializable.getUseSessionTimezone(),
- resultSetSerializable.getFormatDateWithTimeZone(),
- resultSetSerializable.getBinaryFormatter(),
- resultSetSerializable.getDateFormatter(),
- resultSetSerializable.getTimeFormatter(),
- resultSetSerializable.getTimestampNTZFormatter(),
- resultSetSerializable.getTimestampLTZFormatter(),
- resultSetSerializable.getTimestampTZFormatter());
- }
-
public BooleanConverter getBooleanConverter() {
return booleanConverter;
}
diff --git a/src/main/java/net/snowflake/client/core/json/NumberConverter.java b/src/main/java/net/snowflake/client/core/json/NumberConverter.java
index 18f6e96b2..132003359 100644
--- a/src/main/java/net/snowflake/client/core/json/NumberConverter.java
+++ b/src/main/java/net/snowflake/client/core/json/NumberConverter.java
@@ -115,7 +115,7 @@ public BigDecimal getBigDecimal(Object obj, int columnType, Integer scale) throw
if (obj == null) {
return null;
}
- BigDecimal value = getBigDecimal(obj.toString(), columnType);
+ BigDecimal value = new BigDecimal(obj.toString());
value = value.setScale(scale, RoundingMode.HALF_UP);
return value;
}
diff --git a/src/main/java/net/snowflake/client/core/structs/SQLDataCreationHelper.java b/src/main/java/net/snowflake/client/core/structs/SQLDataCreationHelper.java
index fd3257e79..5cfdb5ca2 100644
--- a/src/main/java/net/snowflake/client/core/structs/SQLDataCreationHelper.java
+++ b/src/main/java/net/snowflake/client/core/structs/SQLDataCreationHelper.java
@@ -13,10 +13,11 @@
public class SQLDataCreationHelper {
public static T create(Class type) throws SQLException {
Optional> typeFactory = SnowflakeObjectTypeFactories.get(type);
- return (T)
+ SQLData instance =
typeFactory
.map(Supplier::get)
.orElseGet(() -> createUsingReflection((Class) type));
+ return (T) instance;
}
private static SQLData createUsingReflection(Class extends SQLData> type) {
diff --git a/src/main/java/net/snowflake/client/jdbc/RestRequest.java b/src/main/java/net/snowflake/client/jdbc/RestRequest.java
index 615b20894..fa7826664 100644
--- a/src/main/java/net/snowflake/client/jdbc/RestRequest.java
+++ b/src/main/java/net/snowflake/client/jdbc/RestRequest.java
@@ -399,6 +399,16 @@ public static CloseableHttpResponse execute(
break;
}
+ // If this was a request for an Okta one-time token that failed with a retry-able error,
+ // throw exception to renew the token before trying again.
+ if (String.valueOf(httpRequest.getURI()).contains("okta.com/api/v1/authn")) {
+ throw new SnowflakeSQLException(
+ ErrorCode.AUTHENTICATOR_REQUEST_TIMEOUT,
+ retryCount,
+ true,
+ elapsedMilliForTransientIssues / 1000);
+ }
+
// Make sure that any authenticator specific info that needs to be
// updated get's updated before the next retry. Ex - JWT token
// Check to see if customer set socket/connect timeout has been reached,
diff --git a/src/main/java/net/snowflake/client/jdbc/SFAsyncResultSet.java b/src/main/java/net/snowflake/client/jdbc/SFAsyncResultSet.java
index c50bf4900..bc164de89 100644
--- a/src/main/java/net/snowflake/client/jdbc/SFAsyncResultSet.java
+++ b/src/main/java/net/snowflake/client/jdbc/SFAsyncResultSet.java
@@ -26,6 +26,7 @@
/** SFAsyncResultSet implementation. Note: For Snowflake internal use */
public class SFAsyncResultSet extends SnowflakeBaseResultSet
implements SnowflakeResultSet, ResultSet {
+ private final SFBaseResultSet sfBaseResultSet;
private ResultSet resultSetForNext = new SnowflakeResultSetV1.EmptyResultSet();
private boolean resultSetForNextInitialized = false;
private String queryID;
@@ -46,8 +47,8 @@ public class SFAsyncResultSet extends SnowflakeBaseResultSet
* @throws SQLException if failed to construct snowflake result set metadata
*/
SFAsyncResultSet(SFBaseResultSet sfBaseResultSet, Statement statement) throws SQLException {
-
super(statement);
+ this.sfBaseResultSet = sfBaseResultSet;
this.queryID = sfBaseResultSet.getQueryId();
this.session = sfBaseResultSet.getSession();
this.extraStatement = statement;
@@ -69,6 +70,8 @@ public SFAsyncResultSet(
throws SQLException {
super(resultSetSerializable);
this.queryID = sfBaseResultSet.getQueryId();
+ this.sfBaseResultSet = sfBaseResultSet;
+
this.resultSetMetaData = new SnowflakeResultSetMetaDataV1(sfBaseResultSet.getMetaData());
this.resultSetMetaData.setQueryIdForAsyncResults(this.queryID);
this.resultSetMetaData.setQueryType(SnowflakeResultSetMetaDataV1.QueryType.ASYNC);
@@ -76,6 +79,7 @@ public SFAsyncResultSet(
public SFAsyncResultSet(String queryID, Statement statement) throws SQLException {
super(statement);
+ this.sfBaseResultSet = null;
queryID.trim();
if (!QueryIdValidator.isValid(queryID)) {
throw new SQLException(
diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java
index bd330e68e..4921142a9 100644
--- a/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java
+++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeBaseResultSet.java
@@ -31,12 +31,12 @@
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
-import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.TimeZone;
import net.snowflake.client.core.ArrowSqlInput;
import net.snowflake.client.core.ColumnTypeHelper;
@@ -57,7 +57,6 @@ public abstract class SnowflakeBaseResultSet implements ResultSet {
private final int resultSetType;
private final int resultSetConcurrency;
private final int resultSetHoldability;
- protected SFBaseResultSet sfBaseResultSet;
// Snowflake supports sessionless result set. For this case, there is no
// statement for this result set.
protected final Statement statement;
@@ -65,7 +64,6 @@ public abstract class SnowflakeBaseResultSet implements ResultSet {
protected Map parameters = new HashMap<>();
private int fetchSize = 0;
protected SFBaseSession session = null;
- private static final ObjectMapper OBJECT_MAPPER = ObjectMapperFactory.getObjectMapper();
SnowflakeBaseResultSet(Statement statement) throws SQLException {
this.statement = statement;
@@ -1353,6 +1351,7 @@ public void updateNClob(String columnLabel, Reader reader) throws SQLException {
@Override
public T getObject(int columnIndex, Class type) throws SQLException {
logger.debug("public T getObject(int columnIndex,Class type)", false);
+
if (StructureTypeHelper.isStructureTypeEnabled()) {
if (SQLData.class.isAssignableFrom(type)) {
SQLData instance = (SQLData) SQLDataCreationHelper.create(type);
@@ -1699,8 +1698,6 @@ public Map getMap(int columnIndex, Class type) throws SQLExcep
+ type.getName());
}
}
-
- return resultMap;
}
@Override
diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaDataV1.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaDataV1.java
index 4bc90bd54..94f4bab11 100644
--- a/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaDataV1.java
+++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetMetaDataV1.java
@@ -106,11 +106,10 @@ public boolean isCaseSensitive(int column) throws SQLException {
int colType = getColumnType(column);
switch (colType) {
- // Note: SF types GEOGRAPHY, GEOMETRY are also represented as VARCHAR.
+ // Note: SF types ARRAY, GEOGRAPHY, GEOMETRY are also represented as VARCHAR.
case Types.VARCHAR:
case Types.CHAR:
case Types.STRUCT:
- case Types.ARRAY:
return true;
case Types.INTEGER:
diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetV1.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetV1.java
index bdd8ffcee..83b3d5069 100644
--- a/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetV1.java
+++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeResultSetV1.java
@@ -36,6 +36,7 @@
/** Snowflake ResultSet implementation */
public class SnowflakeResultSetV1 extends SnowflakeBaseResultSet
implements SnowflakeResultSet, ResultSet {
+ private final SFBaseResultSet sfBaseResultSet;
/**
* Constructor takes an inputstream from the API response that we get from executing a SQL
@@ -50,7 +51,6 @@ public class SnowflakeResultSetV1 extends SnowflakeBaseResultSet
*/
public SnowflakeResultSetV1(SFBaseResultSet sfBaseResultSet, Statement statement)
throws SQLException {
-
super(statement);
this.sfBaseResultSet = sfBaseResultSet;
this.resultSetMetaData = new SnowflakeResultSetMetaDataV1(sfBaseResultSet.getMetaData());
@@ -102,6 +102,7 @@ public SnowflakeResultSetV1(
SFBaseResultSet sfBaseResultSet, SnowflakeResultSetSerializableV1 resultSetSerializable)
throws SQLException {
super(resultSetSerializable);
+
this.sfBaseResultSet = sfBaseResultSet;
this.resultSetMetaData = new SnowflakeResultSetMetaDataV1(sfBaseResultSet.getMetaData());
}
diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeType.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeType.java
index 2e483fe5b..d95cacf84 100644
--- a/src/main/java/net/snowflake/client/jdbc/SnowflakeType.java
+++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeType.java
@@ -30,7 +30,6 @@ public enum SnowflakeType {
FIXED,
INTEGER,
OBJECT,
- MAP,
REAL,
TEXT,
TIME,
diff --git a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java
index 82dbca171..85002beea 100644
--- a/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java
+++ b/src/main/java/net/snowflake/client/jdbc/SnowflakeUtil.java
@@ -55,7 +55,7 @@
*/
public class SnowflakeUtil {
- private static final SFLogger logger = SFLoggerFactory.getLogger(SnowflakeUtil.class);
+ static final SFLogger logger = SFLoggerFactory.getLogger(RestRequest.class);
/** Additional data types not covered by standard JDBC */
public static final int EXTRA_TYPES_TIMESTAMP_LTZ = 50000;
@@ -186,7 +186,7 @@ public static SnowflakeColumnMetadata extractColumnMetadata(
String colSrcDatabase = colNode.path("database").asText();
String colSrcSchema = colNode.path("schema").asText();
String colSrcTable = colNode.path("table").asText();
- List fieldsMetadata = getFieldMetadata(jdbcTreatDecimalAsInt, colNode);
+ List fieldsMetadata = getFieldMetadata(fixedColType, colNode);
boolean isAutoIncrement = colNode.path("isAutoIncrement").asBoolean();
@@ -277,7 +277,7 @@ static ColumnTypeInfo getSnowflakeType(
case ARRAY:
columnTypeInfo =
- new ColumnTypeInfo(Types.ARRAY, defaultIfNull(extColTypeName, "ARRAY"), baseType);
+ new ColumnTypeInfo(Types.VARCHAR, defaultIfNull(extColTypeName, "ARRAY"), baseType);
break;
case MAP:
@@ -342,8 +342,8 @@ private static String defaultIfNull(String extColTypeName, String defaultValue)
return Optional.ofNullable(extColTypeName).orElse(defaultValue);
}
- static List createFieldsMetadata(
- ArrayNode fieldsJson, boolean jdbcTreatDecimalAsInt) throws SnowflakeSQLLoggedException {
+ static List createFieldsMetadata(ArrayNode fieldsJson, int fixedColType)
+ throws SnowflakeSQLLoggedException {
List fields = new ArrayList<>();
for (JsonNode node : fieldsJson) {
String colName = node.path("name").asText();
@@ -353,8 +353,7 @@ static List createFieldsMetadata(
boolean nullable = node.path("nullable").asBoolean();
int length = node.path("length").asInt();
boolean fixed = node.path("fixed").asBoolean();
- int fixedColType = jdbcTreatDecimalAsInt && scale == 0 ? Types.BIGINT : Types.DECIMAL;
- List internalFields = getFieldMetadata(jdbcTreatDecimalAsInt, node);
+ List internalFields = getFieldMetadata(fixedColType, node);
JsonNode outputType = node.path("outputType");
JsonNode extColTypeNameNode = node.path("extTypeName");
String extColTypeName = null;
@@ -380,11 +379,11 @@ static List createFieldsMetadata(
return fields;
}
- private static List getFieldMetadata(boolean jdbcTreatDecimalAsInt, JsonNode node)
+ private static List getFieldMetadata(int fixedColType, JsonNode node)
throws SnowflakeSQLLoggedException {
if (!node.path("fields").isEmpty()) {
ArrayNode internalFieldsJson = (ArrayNode) node.path("fields");
- return createFieldsMetadata(internalFieldsJson, jdbcTreatDecimalAsInt);
+ return createFieldsMetadata(internalFieldsJson, fixedColType);
} else {
return new ArrayList<>();
}
diff --git a/src/main/java/net/snowflake/client/jdbc/cloud/storage/SnowflakeGCSClient.java b/src/main/java/net/snowflake/client/jdbc/cloud/storage/SnowflakeGCSClient.java
index 61c31b3ab..25b3bc9dc 100644
--- a/src/main/java/net/snowflake/client/jdbc/cloud/storage/SnowflakeGCSClient.java
+++ b/src/main/java/net/snowflake/client/jdbc/cloud/storage/SnowflakeGCSClient.java
@@ -12,8 +12,6 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.api.gax.paging.Page;
import com.google.api.gax.rpc.FixedHeaderProvider;
-import com.google.auth.oauth2.AccessToken;
-import com.google.auth.oauth2.GoogleCredentials;
import com.google.cloud.storage.Blob;
import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
@@ -45,7 +43,6 @@
import net.snowflake.client.core.ObjectMapperFactory;
import net.snowflake.client.core.SFSession;
import net.snowflake.client.core.SFSessionProperty;
-import net.snowflake.client.core.SnowflakeJdbcInternalApi;
import net.snowflake.client.jdbc.ErrorCode;
import net.snowflake.client.jdbc.FileBackedOutputStream;
import net.snowflake.client.jdbc.MatDesc;
@@ -77,10 +74,6 @@
* @author ppaulus
*/
public class SnowflakeGCSClient implements SnowflakeStorageClient {
- @SnowflakeJdbcInternalApi
- public static final String DISABLE_GCS_DEFAULT_CREDENTIALS_PROPERTY_NAME =
- "net.snowflake.jdbc.disableGcsDefaultCredentials";
-
private static final String GCS_ENCRYPTIONDATAPROP = "encryptiondata";
private static final String localFileSep = systemGetProperty("file.separator");
private static final String GCS_METADATA_PREFIX = "x-goog-meta-";
@@ -1207,19 +1200,13 @@ private void setupGCSClient(
try {
String accessToken = (String) stage.getCredentials().get("GCS_ACCESS_TOKEN");
if (accessToken != null) {
- // We are authenticated with an oauth access token.
- StorageOptions.Builder builder = StorageOptions.newBuilder();
- if (areDisabledGcsDefaultCredentials(session)) {
- logger.debug(
- "Adding explicit credentials to avoid default credential lookup by the GCS client");
- builder.setCredentials(GoogleCredentials.create(new AccessToken(accessToken, null)));
- }
-
// Using GoogleCredential with access token will cause IllegalStateException when the token
// is expired and trying to refresh, which cause error cannot be caught. Instead, set a
// header so we can caught the error code.
+
+ // We are authenticated with an oauth access token.
this.gcsClient =
- builder
+ StorageOptions.newBuilder()
.setHeaderProvider(
FixedHeaderProvider.create("Authorization", "Bearer " + accessToken))
.build()
@@ -1247,12 +1234,6 @@ private void setupGCSClient(
}
}
- private static boolean areDisabledGcsDefaultCredentials(SFSession session) {
- return session != null && session.getDisableGcsDefaultCredentials()
- || SnowflakeUtil.convertSystemPropertyToBooleanValue(
- DISABLE_GCS_DEFAULT_CREDENTIALS_PROPERTY_NAME, false);
- }
-
private static boolean isSuccessStatusCode(int code) {
return code < 300 && code >= 200;
}
diff --git a/src/main/java/net/snowflake/client/jdbc/cloud/storage/StorageClientFactory.java b/src/main/java/net/snowflake/client/jdbc/cloud/storage/StorageClientFactory.java
index ef97c9508..bfa2e3451 100644
--- a/src/main/java/net/snowflake/client/jdbc/cloud/storage/StorageClientFactory.java
+++ b/src/main/java/net/snowflake/client/jdbc/cloud/storage/StorageClientFactory.java
@@ -22,7 +22,7 @@
*/
public class StorageClientFactory {
- private static final SFLogger logger = SFLoggerFactory.getLogger(StorageClientFactory.class);
+ private static final SFLogger logger = SFLoggerFactory.getLogger(SnowflakeS3Client.class);
private static StorageClientFactory factory;
diff --git a/src/test/java/net/snowflake/client/TestUtil.java b/src/test/java/net/snowflake/client/TestUtil.java
index 1f782ec1f..fa53f4c58 100644
--- a/src/test/java/net/snowflake/client/TestUtil.java
+++ b/src/test/java/net/snowflake/client/TestUtil.java
@@ -116,13 +116,13 @@ public static void withSchema(Statement statement, String schemaName, ThrowingRu
* @param action action to execute when schema was created
* @throws Exception when any error occurred
*/
- public static void withRandomSchema(
- Statement statement, ThrowingConsumer action) throws Exception {
+ public static void withRandomSchema(Statement statement, ThrowingConsumer action)
+ throws Exception {
String customSchema =
GENERATED_SCHEMA_PREFIX + SnowflakeUtil.randomAlphaNumeric(5).toUpperCase();
try {
statement.execute("CREATE OR REPLACE SCHEMA " + customSchema);
- action.accept(customSchema);
+ action.call(customSchema);
} finally {
statement.execute("DROP SCHEMA " + customSchema);
}
diff --git a/src/test/java/net/snowflake/client/ThrowingConsumer.java b/src/test/java/net/snowflake/client/ThrowingConsumer.java
index d5a47cd5e..8b6f8c001 100644
--- a/src/test/java/net/snowflake/client/ThrowingConsumer.java
+++ b/src/test/java/net/snowflake/client/ThrowingConsumer.java
@@ -1,6 +1,6 @@
package net.snowflake.client;
@FunctionalInterface
-public interface ThrowingConsumer {
- void accept(A parameter) throws T;
+public interface ThrowingConsumer {
+ void call(T parameter) throws Exception;
}
diff --git a/src/test/java/net/snowflake/client/core/SessionUtilLatestIT.java b/src/test/java/net/snowflake/client/core/SessionUtilLatestIT.java
index f3e60f56b..bedd77438 100644
--- a/src/test/java/net/snowflake/client/core/SessionUtilLatestIT.java
+++ b/src/test/java/net/snowflake/client/core/SessionUtilLatestIT.java
@@ -390,4 +390,79 @@ public void testOktaAuthGetFail() throws Throwable {
assertEquals(SqlState.IO_ERROR, e.getSQLState());
}
}
+
+ private SFLoginInput createOktaLoginInput() {
+ SFLoginInput input = new SFLoginInput();
+ input.setServerUrl("https://testauth.okta.com");
+ input.setUserName("MOCK_USERNAME");
+ input.setPassword("MOCK_PASSWORD");
+ input.setAccountName("MOCK_ACCOUNT_NAME");
+ input.setAppId("MOCK_APP_ID");
+ input.setOCSPMode(OCSPMode.FAIL_OPEN);
+ input.setHttpClientSettingsKey(new HttpClientSettingsKey(OCSPMode.FAIL_OPEN));
+ input.setLoginTimeout(1000);
+ input.setSessionParameters(new HashMap<>());
+ input.setAuthenticator("https://testauth.okta.com");
+ return input;
+ }
+
+ // Testing retry with Okta calls the service to get a new unique token. This is valid after
+ // version 3.15.0.
+ @Test
+ public void testOktaAuthRetry() throws Throwable {
+ SFLoginInput loginInput = createOktaLoginInput();
+ Map connectionPropertiesMap = initConnectionPropertiesMap();
+ SnowflakeSQLException ex =
+ new SnowflakeSQLException(ErrorCode.AUTHENTICATOR_REQUEST_TIMEOUT, 0, true, 0);
+ try (MockedStatic mockedHttpUtil = mockStatic(HttpUtil.class)) {
+ mockedHttpUtil
+ .when(
+ () ->
+ HttpUtil.executeGeneralRequest(
+ Mockito.any(HttpPost.class),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.nullable(HttpClientSettingsKey.class)))
+ .thenReturn(
+ "{\"data\":{\"tokenUrl\":\"https://testauth.okta.com/api/v1/authn\","
+ + "\"ssoUrl\":\"https://testauth.okta.com/app/snowflake/abcdefghijklmnopqrstuvwxyz/sso/saml\","
+ + "\"proofKey\":null},\"code\":null,\"message\":null,\"success\":true}")
+ .thenThrow(ex)
+ .thenReturn(
+ "{\"data\":{\"tokenUrl\":\"https://testauth.okta.com/api/v1/authn\","
+ + "\"ssoUrl\":\"https://testauth.okta.com/app/snowflake/abcdefghijklmnopqrstuvwxyz/sso/saml\","
+ + "\"proofKey\":null},\"code\":null,\"message\":null,\"success\":true}");
+
+ mockedHttpUtil
+ .when(
+ () ->
+ HttpUtil.executeRequestWithoutCookies(
+ Mockito.any(HttpRequestBase.class),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.nullable(AtomicBoolean.class),
+ Mockito.nullable(HttpClientSettingsKey.class)))
+ .thenReturn(
+ "{\"expiresAt\":\"2023-10-13T19:18:09.000Z\",\"status\":\"SUCCESS\",\"sessionToken\":\"testsessiontoken\"}");
+
+ mockedHttpUtil
+ .when(
+ () ->
+ HttpUtil.executeGeneralRequest(
+ Mockito.any(HttpGet.class),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.anyInt(),
+ Mockito.nullable(HttpClientSettingsKey.class)))
+ .thenReturn("");
+
+ SessionUtil.openSession(loginInput, connectionPropertiesMap, "ALL");
+ }
+ }
}
diff --git a/src/test/java/net/snowflake/client/jdbc/ConnectionIT.java b/src/test/java/net/snowflake/client/jdbc/ConnectionIT.java
index 14b9f2d71..68d337aff 100644
--- a/src/test/java/net/snowflake/client/jdbc/ConnectionIT.java
+++ b/src/test/java/net/snowflake/client/jdbc/ConnectionIT.java
@@ -33,8 +33,10 @@
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
@@ -387,6 +389,40 @@ public void testDataSourceOktaSerialization() throws Exception {
con.close();
}
+ @Test
+ @Ignore
+ public void testDataSourceOktaGenerates429StatusCode() throws Exception {
+ // test with username/password authentication
+ // set up DataSource object and ensure connection works
+ Map params = getConnectionParameters();
+ SnowflakeBasicDataSource ds = new SnowflakeBasicDataSource();
+ ds.setServerName(params.get("host"));
+ ds.setSsl("on".equals(params.get("ssl")));
+ ds.setAccount(params.get("account"));
+ ds.setPortNumber(Integer.parseInt(params.get("port")));
+ ds.setUser(params.get("ssoUser"));
+ ds.setPassword(params.get("ssoPassword"));
+ ds.setAuthenticator("");
+ Runnable r =
+ () -> {
+ try {
+ ds.getConnection();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ };
+ List threadList = new ArrayList<>();
+ for (int i = 0;
+ i < 30;
+ ++i) { // https://docs.snowflake.com/en/user-guide/admin-security-fed-auth-use#http-429-errors
+ threadList.add(new Thread(r));
+ }
+ threadList.forEach(Thread::start);
+ for (Thread thread : threadList) {
+ thread.join();
+ }
+ }
+
@Test
@ConditionalIgnore(condition = RunningOnGithubAction.class)
public void testConnectUsingKeyPair() throws Exception {
diff --git a/src/test/java/net/snowflake/client/jdbc/ConnectionLatestIT.java b/src/test/java/net/snowflake/client/jdbc/ConnectionLatestIT.java
index b9a406176..15d8b2f80 100644
--- a/src/test/java/net/snowflake/client/jdbc/ConnectionLatestIT.java
+++ b/src/test/java/net/snowflake/client/jdbc/ConnectionLatestIT.java
@@ -403,10 +403,10 @@ public void testQueryStatusErrorMessageAndErrorCodeChangeOnAsyncQuery() throws S
SnowflakeResultSet sfResultSet = rs1.unwrap(SnowflakeResultSet.class);
// status should change state to RUNNING and then to SUCCESS
await()
- .atMost(Duration.ofSeconds(10))
+ .atMost(Duration.ofSeconds(5))
.until(() -> sfResultSet.getStatusV2().getStatus(), equalTo(QueryStatus.RUNNING));
await()
- .atMost(Duration.ofSeconds(50))
+ .atMost(Duration.ofSeconds(5))
.until(() -> sfResultSet.getStatusV2().getStatus(), equalTo(QueryStatus.SUCCESS));
}
}
diff --git a/src/test/java/net/snowflake/client/jdbc/MockConnectionTest.java b/src/test/java/net/snowflake/client/jdbc/MockConnectionTest.java
index c763606fe..65163a938 100644
--- a/src/test/java/net/snowflake/client/jdbc/MockConnectionTest.java
+++ b/src/test/java/net/snowflake/client/jdbc/MockConnectionTest.java
@@ -50,7 +50,6 @@
import net.snowflake.client.core.json.Converters;
import net.snowflake.client.jdbc.telemetry.Telemetry;
import net.snowflake.client.jdbc.telemetry.TelemetryData;
-import net.snowflake.common.core.SFBinaryFormat;
import net.snowflake.common.core.SnowflakeDateTimeFormat;
import org.junit.Test;
import org.junit.experimental.categories.Category;
@@ -882,21 +881,6 @@ public ResultSet createResultSet(String queryID, Statement statement) throws SQL
@Override
public SnowflakeBaseResultSet createResultSet(SFBaseResultSet resultSet, Statement statement)
throws SQLException {
- Converters convertes =
- new Converters(
- null,
- new SFSession(),
- 0,
- false,
- false,
- false,
- false,
- SFBinaryFormat.BASE64,
- null,
- null,
- null,
- null,
- null);
return new SnowflakeResultSetV1(resultSet, statement);
}
diff --git a/src/test/java/net/snowflake/client/jdbc/RestRequestTest.java b/src/test/java/net/snowflake/client/jdbc/RestRequestTest.java
index 0654cc73d..ed6e165d1 100644
--- a/src/test/java/net/snowflake/client/jdbc/RestRequestTest.java
+++ b/src/test/java/net/snowflake/client/jdbc/RestRequestTest.java
@@ -359,6 +359,20 @@ public void testExceptionAuthBasedTimeout() throws IOException {
}
}
+ @Test
+ public void testExceptionAuthBasedTimeoutFor429ErrorCode() throws IOException {
+ CloseableHttpClient client = mock(CloseableHttpClient.class);
+ when(client.execute(any(HttpUriRequest.class)))
+ .thenAnswer((Answer) invocation -> retryLoginResponse());
+
+ try {
+ execute(client, "login-request.com/?requestId=abcd-1234", 2, 1, 30000, true, false);
+ } catch (SnowflakeSQLException ex) {
+ assertThat(
+ ex.getErrorCode(), equalTo(ErrorCode.AUTHENTICATOR_REQUEST_TIMEOUT.getMessageCode()));
+ }
+ }
+
@Test
public void testNoRetry() throws IOException, SnowflakeSQLException {
boolean telemetryEnabled = TelemetryService.getInstance().isEnabled();
diff --git a/src/test/java/net/snowflake/client/jdbc/ResultSetFeatureNotSupportedIT.java b/src/test/java/net/snowflake/client/jdbc/ResultSetFeatureNotSupportedIT.java
index 2535a6579..539784120 100644
--- a/src/test/java/net/snowflake/client/jdbc/ResultSetFeatureNotSupportedIT.java
+++ b/src/test/java/net/snowflake/client/jdbc/ResultSetFeatureNotSupportedIT.java
@@ -117,6 +117,7 @@ private void checkFeatureNotSupportedException(ResultSet resultSet) throws SQLEx
expectFeatureNotSupportedException(() -> resultSet.getObject(1, Collections.emptyMap()));
expectFeatureNotSupportedException(() -> resultSet.getRef(1));
expectFeatureNotSupportedException(() -> resultSet.getBlob(1));
+ expectFeatureNotSupportedException(() -> resultSet.getArray(1));
expectFeatureNotSupportedException(() -> resultSet.getURL(1));
expectFeatureNotSupportedException(() -> resultSet.getRowId(1));
expectFeatureNotSupportedException(() -> resultSet.getNClob(1));
diff --git a/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java b/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java
index 71f8d590b..3fea6ef8c 100644
--- a/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java
+++ b/src/test/java/net/snowflake/client/jdbc/ResultSetStructuredTypesLatestIT.java
@@ -19,8 +19,6 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
-import java.util.List;
-import java.util.Map;
import net.snowflake.client.ConditionalIgnoreRule;
import net.snowflake.client.RunningOnGithubAction;
import net.snowflake.client.ThrowingConsumer;
@@ -91,13 +89,17 @@ public void testMapStructToObjectWithReflection() throws SQLException {
private void testMapJson(boolean registerFactory) throws SQLException {
if (registerFactory) {
SnowflakeObjectTypeFactories.register(SimpleClass.class, SimpleClass::new);
+ } else {
+ SnowflakeObjectTypeFactories.unregister(SimpleClass.class);
+ }
+ try (Connection connection = init();
+ Statement statement = connection.createStatement();
+ ResultSet resultSet =
+ statement.executeQuery("select {'string':'a'}::OBJECT(string VARCHAR)"); ) {
+ resultSet.next();
+ SimpleClass object = resultSet.getObject(1, SimpleClass.class);
+ assertEquals("a", object.getString());
}
- withFirstRow(
- "select {'string':'a'}::OBJECT(string VARCHAR)",
- (resultSet) -> {
- SimpleClass object = resultSet.getObject(1, SimpleClass.class);
- assertEquals("a", object.getString());
- });
}
@Test
@@ -156,12 +158,12 @@ private void testMapAllTypes(boolean registerFactory) throws SQLException {
resultSet.next();
AllTypesClass object = resultSet.getObject(1, AllTypesClass.class);
assertEquals("a", object.getString());
- assertEquals(new Byte("1"), object.getB());
- assertEquals(Short.valueOf("2"), object.getS());
- assertEquals(Integer.valueOf(3), object.getI());
- assertEquals(Long.valueOf(4), object.getL());
- assertEquals(Float.valueOf(1.1f), object.getF(), 0.01);
- assertEquals(Double.valueOf(2.2), object.getD(), 0.01);
+ assertEquals(1, (long) object.getB());
+ assertEquals(2, (long) object.getS());
+ assertEquals(3, (long) object.getI());
+ assertEquals(4, (long) object.getL());
+ assertEquals(1.1, (double) object.getF(), 0.01);
+ assertEquals(2.2, (double) object.getD(), 0.01);
assertEquals(BigDecimal.valueOf(3.3), object.getBd());
assertEquals(
Timestamp.valueOf(LocalDateTime.of(2021, 12, 22, 9, 43, 44)), object.getTimestampLtz());
diff --git a/src/test/java/net/snowflake/client/jdbc/SnowflakeDriverLatestIT.java b/src/test/java/net/snowflake/client/jdbc/SnowflakeDriverLatestIT.java
index e76e5c60e..744ffccf6 100644
--- a/src/test/java/net/snowflake/client/jdbc/SnowflakeDriverLatestIT.java
+++ b/src/test/java/net/snowflake/client/jdbc/SnowflakeDriverLatestIT.java
@@ -8,7 +8,6 @@
import static net.snowflake.client.jdbc.SnowflakeDriverIT.findFile;
import static net.snowflake.client.jdbc.SnowflakeResultSetSerializableV1.mapper;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -47,9 +46,7 @@
import net.snowflake.client.core.Constants;
import net.snowflake.client.core.OCSPMode;
import net.snowflake.client.core.SFSession;
-import net.snowflake.client.core.SFSessionProperty;
import net.snowflake.client.core.SFStatement;
-import net.snowflake.client.jdbc.cloud.storage.SnowflakeGCSClient;
import net.snowflake.client.jdbc.cloud.storage.SnowflakeStorageClient;
import net.snowflake.client.jdbc.cloud.storage.StageInfo;
import net.snowflake.client.jdbc.cloud.storage.StorageClientFactory;
@@ -841,7 +838,7 @@ public void testGeoOutputTypes() throws Throwable {
regularStatement, false, "geoJson", "OBJECT", "java.lang.String", Types.VARCHAR);
testGeoOutputTypeSingle(
- regularStatement, true, "geoJson", "GEOGRAPHY", "java.lang.String", Types.VARCHAR);
+ regularStatement, true, "geoJson", "GEOGRAPHY", "java.lang.String", Types.STRUCT);
testGeoOutputTypeSingle(
regularStatement, false, "wkt", "VARCHAR", "java.lang.String", Types.VARCHAR);
@@ -989,10 +986,10 @@ public void testGeometryOutputTypes() throws Throwable {
"insert into t_geo2 values ('POINT(0 0)'), ('LINESTRING(1 1, 2 2)')");
testGeometryOutputTypeSingle(
- regularStatement, true, "geoJson", "GEOMETRY", "java.lang.String", Types.VARCHAR);
+ regularStatement, true, "geoJson", "GEOMETRY", "java.lang.String", Types.STRUCT);
testGeometryOutputTypeSingle(
- regularStatement, true, "wkt", "GEOMETRY", "java.lang.String", Types.VARCHAR);
+ regularStatement, true, "wkt", "GEOMETRY", "java.lang.String", Types.STRUCT);
} finally {
if (regularStatement != null) {
@@ -1108,67 +1105,58 @@ private void testGeometryMetadataSingle(
@Test
@ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class)
public void testPutGetGcsDownscopedCredential() throws Throwable {
+ Connection connection = null;
+ Statement statement = null;
Properties paramProperties = new Properties();
paramProperties.put("GCS_USE_DOWNSCOPED_CREDENTIAL", true);
- try (Connection connection = getConnection("gcpaccount", paramProperties);
- Statement statement = connection.createStatement()) {
- putAndGetFile(statement);
- }
- }
+ try {
+ connection = getConnection("gcpaccount", paramProperties);
- /** Added in > 3.15.0 */
- @Test
- @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class)
- public void testPutGetGcsDownscopedCredentialWithDisabledDefaultCredentials() throws Throwable {
- Properties paramProperties = new Properties();
- paramProperties.put("GCS_USE_DOWNSCOPED_CREDENTIAL", true);
- paramProperties.put(SFSessionProperty.DISABLE_GCS_DEFAULT_CREDENTIALS.getPropertyKey(), true);
- try (Connection connection = getConnection("gcpaccount", paramProperties);
- Statement statement = connection.createStatement()) {
- putAndGetFile(statement);
- }
- }
+ statement = connection.createStatement();
- private void putAndGetFile(Statement statement) throws Throwable {
- String sourceFilePath = getFullPathFileInResource(TEST_DATA_FILE_2);
+ String sourceFilePath = getFullPathFileInResource(TEST_DATA_FILE_2);
- File destFolder = tmpFolder.newFolder();
- String destFolderCanonicalPath = destFolder.getCanonicalPath();
- String destFolderCanonicalPathWithSeparator = destFolderCanonicalPath + File.separator;
+ File destFolder = tmpFolder.newFolder();
+ String destFolderCanonicalPath = destFolder.getCanonicalPath();
+ String destFolderCanonicalPathWithSeparator = destFolderCanonicalPath + File.separator;
- try {
- statement.execute("CREATE OR REPLACE STAGE testPutGet_stage");
+ try {
+ statement.execute("CREATE OR REPLACE STAGE testPutGet_stage");
- assertTrue(
- "Failed to put a file",
- statement.execute("PUT file://" + sourceFilePath + " @testPutGet_stage"));
+ assertTrue(
+ "Failed to put a file",
+ statement.execute("PUT file://" + sourceFilePath + " @testPutGet_stage"));
- findFile(statement, "ls @testPutGet_stage/");
+ findFile(statement, "ls @testPutGet_stage/");
- // download the file we just uploaded to stage
- assertTrue(
- "Failed to get a file",
- statement.execute(
- "GET @testPutGet_stage 'file://" + destFolderCanonicalPath + "' parallel=8"));
+ // download the file we just uploaded to stage
+ assertTrue(
+ "Failed to get a file",
+ statement.execute(
+ "GET @testPutGet_stage 'file://" + destFolderCanonicalPath + "' parallel=8"));
- // Make sure that the downloaded file exists, it should be gzip compressed
- File downloaded = new File(destFolderCanonicalPathWithSeparator + TEST_DATA_FILE_2 + ".gz");
- assert (downloaded.exists());
+ // Make sure that the downloaded file exists, it should be gzip compressed
+ File downloaded = new File(destFolderCanonicalPathWithSeparator + TEST_DATA_FILE_2 + ".gz");
+ assert (downloaded.exists());
- Process p =
- Runtime.getRuntime()
- .exec("gzip -d " + destFolderCanonicalPathWithSeparator + TEST_DATA_FILE_2 + ".gz");
- p.waitFor();
+ Process p =
+ Runtime.getRuntime()
+ .exec("gzip -d " + destFolderCanonicalPathWithSeparator + TEST_DATA_FILE_2 + ".gz");
+ p.waitFor();
- File original = new File(sourceFilePath);
- File unzipped = new File(destFolderCanonicalPathWithSeparator + TEST_DATA_FILE_2);
- System.out.println(
- "Original file: " + original.getAbsolutePath() + ", size: " + original.length());
- System.out.println(
- "Unzipped file: " + unzipped.getAbsolutePath() + ", size: " + unzipped.length());
- assert (original.length() == unzipped.length());
+ File original = new File(sourceFilePath);
+ File unzipped = new File(destFolderCanonicalPathWithSeparator + TEST_DATA_FILE_2);
+ System.out.println(
+ "Original file: " + original.getAbsolutePath() + ", size: " + original.length());
+ System.out.println(
+ "Unzipped file: " + unzipped.getAbsolutePath() + ", size: " + unzipped.length());
+ assert (original.length() == unzipped.length());
+ } finally {
+ statement.execute("DROP STAGE IF EXISTS testGetPut_stage");
+ statement.close();
+ }
} finally {
- statement.execute("DROP STAGE IF EXISTS testGetPut_stage");
+ closeSQLObjects(null, statement, connection);
}
}
@@ -1509,7 +1497,7 @@ public void testAzureS3UploadStreamingIngestFileMetadata() throws Throwable {
((SnowflakeFileTransferMetadataV1) oneMetadata).getStageInfo(),
1,
null,
- /* session= */ null);
+ /*session = */ null);
String location =
((SnowflakeFileTransferMetadataV1) oneMetadata).getStageInfo().getLocation();
@@ -1549,7 +1537,7 @@ public void testNoSpaceLeftOnDeviceException() throws SQLException {
new SnowflakeFileTransferAgent(command, sfSession, sfStatement);
StageInfo info = sfAgent.getStageInfo();
SnowflakeStorageClient client =
- StorageClientFactory.getFactory().createClient(info, 1, null, /* session= */ null);
+ StorageClientFactory.getFactory().createClient(info, 1, null, /*session = */ null);
client.handleStorageException(
new StorageException(
@@ -1625,72 +1613,58 @@ public void testUploadWithGCSPresignedUrlWithoutConnection() throws Throwable {
@Test
@ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class)
public void testUploadWithGCSDownscopedCredentialWithoutConnection() throws Throwable {
- uploadWithGCSDownscopedCredentialWithoutConnection();
- }
-
- /** Added in > 3.15.0 */
- @Test
- @ConditionalIgnoreRule.ConditionalIgnore(condition = RunningOnGithubAction.class)
- public void
- testUploadWithGCSDownscopedCredentialAndDisabledGcsDefaultCredentialsWithoutConnection()
- throws Throwable {
- System.setProperty(SnowflakeGCSClient.DISABLE_GCS_DEFAULT_CREDENTIALS_PROPERTY_NAME, "true");
- try {
- uploadWithGCSDownscopedCredentialWithoutConnection();
- } finally {
- System.clearProperty(SnowflakeGCSClient.DISABLE_GCS_DEFAULT_CREDENTIALS_PROPERTY_NAME);
- }
- }
-
- private void uploadWithGCSDownscopedCredentialWithoutConnection() throws Throwable {
+ Connection connection = null;
File destFolder = tmpFolder.newFolder();
String destFolderCanonicalPath = destFolder.getCanonicalPath();
- Properties paramProperties = new Properties();
- paramProperties.put("GCS_USE_DOWNSCOPED_CREDENTIAL", true);
- try (Connection connection = getConnection("gcpaccount", paramProperties);
- Statement statement = connection.createStatement(); ) {
- try {
- // create a stage to put the file in
- statement.execute("CREATE OR REPLACE STAGE " + testStageName);
+ try {
+ Properties paramProperties = new Properties();
+ paramProperties.put("GCS_USE_DOWNSCOPED_CREDENTIAL", true);
+ connection = getConnection("gcpaccount", paramProperties);
+ // connection = getConnection(null, paramProperties);
+ Statement statement = connection.createStatement();
- SFSession sfSession = connection.unwrap(SnowflakeConnectionV1.class).getSfSession();
+ // create a stage to put the file in
+ statement.execute("CREATE OR REPLACE STAGE " + testStageName);
- // Test put file with internal compression
- String putCommand = "put file:///dummy/path/file1.gz @" + testStageName;
- SnowflakeFileTransferAgent sfAgent =
- new SnowflakeFileTransferAgent(putCommand, sfSession, new SFStatement(sfSession));
- List metadataList = sfAgent.getFileTransferMetadatas();
- assertEquals(1, metadataList.size());
- SnowflakeFileTransferMetadata oneMetadata = metadataList.get(0);
- assertFalse(oneMetadata.isForOneFile());
-
- // Upload multiple file with the same SnowflakeFileTransferMetadata
- String[] fileNames = {TEST_DATA_FILE, TEST_DATA_FILE_2};
- for (String fileName : fileNames) {
- String srcPath = getFullPathFileInResource(fileName);
- try (InputStream inputStream = new FileInputStream(srcPath)) {
- // upload file 1
- String targetFileName = fileName + ".gz";
- SnowflakeFileTransferAgent.uploadWithoutConnection(
- SnowflakeFileTransferConfig.Builder.newInstance()
- .setSnowflakeFileTransferMetadata(oneMetadata)
- .setUploadStream(inputStream)
- .setDestFileName(targetFileName)
- .setRequireCompress(true)
- .setNetworkTimeoutInMilli(0)
- .setOcspMode(OCSPMode.FAIL_OPEN)
- .build());
- assertTrue(
- "Failed to get files with down-scoped token",
- statement.execute(
- "GET @" + testStageName + " 'file://" + destFolderCanonicalPath + "/'"));
- assertTrue(
- isFileContentEqual(
- srcPath, false, destFolderCanonicalPath + "/" + targetFileName, true));
- }
- }
- } finally {
- statement.execute("DROP STAGE if exists " + testStageName);
+ SFSession sfSession = connection.unwrap(SnowflakeConnectionV1.class).getSfSession();
+
+ // Test put file with internal compression
+ String putCommand = "put file:///dummy/path/file1.gz @" + testStageName;
+ SnowflakeFileTransferAgent sfAgent =
+ new SnowflakeFileTransferAgent(putCommand, sfSession, new SFStatement(sfSession));
+ List metadataList = sfAgent.getFileTransferMetadatas();
+ assert (metadataList.size() == 1);
+ SnowflakeFileTransferMetadata oneMetadata = metadataList.get(0);
+ assert (!oneMetadata.isForOneFile());
+
+ // Upload multiple file with the same SnowflakeFileTransferMetadata
+ String[] fileNames = {TEST_DATA_FILE, TEST_DATA_FILE_2};
+ for (String fileName : fileNames) {
+ String srcPath = getFullPathFileInResource(fileName);
+ InputStream inputStream = new FileInputStream(srcPath);
+ // upload file 1
+ String targetFileName = fileName + ".gz";
+ SnowflakeFileTransferAgent.uploadWithoutConnection(
+ SnowflakeFileTransferConfig.Builder.newInstance()
+ .setSnowflakeFileTransferMetadata(oneMetadata)
+ .setUploadStream(inputStream)
+ .setDestFileName(targetFileName)
+ .setRequireCompress(true)
+ .setNetworkTimeoutInMilli(0)
+ .setOcspMode(OCSPMode.FAIL_OPEN)
+ .build());
+ assertTrue(
+ "Failed to get files with down-scoped token",
+ statement.execute(
+ "GET @" + testStageName + " 'file://" + destFolderCanonicalPath + "/'"));
+ assert (isFileContentEqual(
+ srcPath, false, destFolderCanonicalPath + "/" + targetFileName, true));
+ inputStream.close();
+ }
+ } finally {
+ if (connection != null) {
+ connection.createStatement().execute("DROP STAGE if exists " + testStageName);
+ connection.close();
}
}
}
diff --git a/thin_public_pom.xml b/thin_public_pom.xml
index 239e31e34..474f8e44c 100644
--- a/thin_public_pom.xml
+++ b/thin_public_pom.xml
@@ -44,7 +44,6 @@
2.21.0
2.22.6
1.12.0
- 1.19.0
2.31.0
32.1.1-jre
1.43.3
@@ -145,11 +144,6 @@
gax
${google.gax.version}
-
- com.google.auth
- google-auth-library-oauth2-http
- ${google.auth.library.oauth2.http.version}
-
com.google.cloud
google-cloud-core