diff --git a/FIPS/pom.xml b/FIPS/pom.xml
index 04fa6a5f5..dd994a297 100644
--- a/FIPS/pom.xml
+++ b/FIPS/pom.xml
@@ -429,6 +429,10 @@
org.jsoup
${shadeBase}.org.jsoup
+
+ com.github.luben.zstd
+ ${shadeBase}.com.github.luben.zstd
+
com.nimbusds
${shadeBase}.com.nimbusds
diff --git a/FIPS/scripts/check_content.sh b/FIPS/scripts/check_content.sh
index 8b818b1b4..fa675655e 100755
--- a/FIPS/scripts/check_content.sh
+++ b/FIPS/scripts/check_content.sh
@@ -1,12 +1,12 @@
#!/bin/bash -e
-# scripts used to check if all dependency is shaded into snowflake internal path
+# scripts used to check if all dependencies are shaded into snowflake internal path
set -o pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-if jar tvf $DIR/../target/snowflake-jdbc-fips.jar | awk '{print $8}' | grep -v -E "^(net|com)/snowflake" | grep -v -E "(com|net)/\$" | grep -v -E "^META-INF" | grep -v -E "^mozilla" | grep -v -E "^com/sun/jna" | grep -v com/sun/ | grep -v mime.types; then
+if jar tvf $DIR/../target/snowflake-jdbc-fips.jar | awk '{print $8}' | grep -v -E "^(net|com)/snowflake" | grep -v -E "(com|net)/\$" | grep -v -E "^META-INF" | grep -v -E "^mozilla" | grep -v -E "^com/sun/jna" | grep -v com/sun/ | grep -v mime.types | grep -v -E "^aix/" | grep -v -E "^darwin/" | grep -v -E "^freebsd/" | grep -v -E "^linux/" | grep -v -E "^win/"; then
echo "[ERROR] JDBC jar includes class not under the snowflake namespace"
exit 1
fi
diff --git a/ci/scripts/check_content.sh b/ci/scripts/check_content.sh
index a9c0768b6..ce6f34180 100755
--- a/ci/scripts/check_content.sh
+++ b/ci/scripts/check_content.sh
@@ -8,12 +8,12 @@ set -o pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
-if jar tvf $DIR/../../target/snowflake-jdbc${package_modifier}.jar | awk '{print $8}' | grep -v -E "^(net|com)/snowflake" | grep -v -E "(com|net)/\$" | grep -v -E "^META-INF" | grep -v -E "^mozilla" | grep -v -E "^com/sun/jna" | grep -v com/sun/ | grep -v mime.types; then
+if jar tvf $DIR/../../target/snowflake-jdbc${package_modifier}.jar | awk '{print $8}' | grep -v -E "^(net|com)/snowflake" | grep -v -E "(com|net)/\$" | grep -v -E "^META-INF" | grep -v -E "^mozilla" | grep -v -E "^com/sun/jna" | grep -v com/sun/ | grep -v mime.types | grep -v -E "^aix/" | grep -v -E "^darwin/" | grep -v -E "^freebsd/" | grep -v -E "^linux/" | grep -v -E "^win/"; then
echo "[ERROR] JDBC jar includes class not under the snowflake namespace"
exit 1
fi
-if jar tvf $DIR/../../target/snowflake-jdbc${package_modifier}.jar | awk '{print $8}' | grep -E "^META-INF/versions/.*.class" | grep -v -E "^META-INF/versions/.*/(net|com)/snowflake"; then
- echo "[ERROR] JDBC jar includes multi release classes not under the snowflake namespace"
+if jar tvf $DIR/../../target/snowflake-jdbc${package_modifier}.jar | awk '{print $8}' | grep -E "^META-INF/versions/.*.class" | grep -v -E "^META-INF/versions/.*/(net|com)/snowflake" | grep -v -E "^aix/" | grep -v -E "^darwin/" | grep -v -E "^freebsd/" | grep -v -E "^linux/" | grep -v -E "^win/"; then
+ echo "[ERROR] JDBC jar includes multi-release classes not under the snowflake namespace"
exit 1
fi
diff --git a/linkage-checker-exclusion-rules.xml b/linkage-checker-exclusion-rules.xml
index 8bad89714..0f6275008 100644
--- a/linkage-checker-exclusion-rules.xml
+++ b/linkage-checker-exclusion-rules.xml
@@ -19,11 +19,6 @@
Optional
-
-
-
- Optional
-
diff --git a/parent-pom.xml b/parent-pom.xml
index 28412d161..04dc541e0 100644
--- a/parent-pom.xml
+++ b/parent-pom.xml
@@ -19,6 +19,7 @@
1.10.0
4.5.14
4.4.16
+ 1.5.6-5
17.0.0
9.3
1.8.1
@@ -327,6 +328,11 @@
httpcore
${apache.httpcore.version}
+
+ com.github.luben
+ zstd-jni
+ ${zstd-jni.version}
+
org.apache.tika
tika-core
@@ -644,6 +650,10 @@
org.apache.httpcomponents
httpcore
+
+ com.github.luben
+ zstd-jni
+
org.apache.tika
tika-core
diff --git a/pom.xml b/pom.xml
index 096641174..e41cb7f62 100644
--- a/pom.xml
+++ b/pom.xml
@@ -947,6 +947,10 @@
android.annotation
${shadeBase}.android.annotation
+
+ com.github.luben.zstd
+ ${shadeBase}.com.github.luben.zstd
+
diff --git a/src/main/java/net/snowflake/client/jdbc/DefaultResultStreamProvider.java b/src/main/java/net/snowflake/client/jdbc/DefaultResultStreamProvider.java
index 3ee556bb4..567db8fa1 100644
--- a/src/main/java/net/snowflake/client/jdbc/DefaultResultStreamProvider.java
+++ b/src/main/java/net/snowflake/client/jdbc/DefaultResultStreamProvider.java
@@ -2,6 +2,7 @@
import static net.snowflake.client.core.Constants.MB;
+import com.github.luben.zstd.ZstdInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;
@@ -153,6 +154,8 @@ private InputStream detectContentEncodingAndGetInputStream(HttpResponse response
if ("gzip".equalsIgnoreCase(encoding.getValue())) {
/* specify buffer size for GZIPInputStream */
inputStream = new GZIPInputStream(is, STREAM_BUFFER_SIZE);
+ } else if ("zstd".equalsIgnoreCase(encoding.getValue())) {
+ inputStream = new ZstdInputStream(is);
} else {
throw new SnowflakeSQLException(
SqlState.INTERNAL_ERROR,
diff --git a/src/test/java/net/snowflake/client/jdbc/DefaultResultStreamProviderTest.java b/src/test/java/net/snowflake/client/jdbc/DefaultResultStreamProviderTest.java
new file mode 100644
index 000000000..b78bf3a5e
--- /dev/null
+++ b/src/test/java/net/snowflake/client/jdbc/DefaultResultStreamProviderTest.java
@@ -0,0 +1,120 @@
+package net.snowflake.client.jdbc;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.github.luben.zstd.ZstdInputStream;
+import com.github.luben.zstd.ZstdOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.lang.reflect.Method;
+import java.nio.charset.StandardCharsets;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.junit.Before;
+import org.junit.Test;
+
+public class DefaultResultStreamProviderTest {
+
+ private DefaultResultStreamProvider resultStreamProvider;
+ private HttpResponse mockResponse;
+
+ @Before
+ public void setUp() {
+ resultStreamProvider = new DefaultResultStreamProvider();
+ mockResponse = mock(HttpResponse.class);
+ }
+
+ private InputStream invokeDetectContentEncodingAndGetInputStream(
+ HttpResponse response, InputStream inputStream) throws Exception {
+ Method method =
+ DefaultResultStreamProvider.class.getDeclaredMethod(
+ "detectContentEncodingAndGetInputStream", HttpResponse.class, InputStream.class);
+ method.setAccessible(true);
+ return (InputStream) method.invoke(resultStreamProvider, response, inputStream);
+ }
+
+ @Test
+ public void testDetectContentEncodingAndGetInputStream_Gzip() throws Exception {
+ // Mocking gzip content encoding
+ Header encodingHeader = mock(Header.class);
+ when(encodingHeader.getValue()).thenReturn("gzip");
+ when(mockResponse.getFirstHeader("Content-Encoding")).thenReturn(encodingHeader);
+
+ // Original data to compress and validate
+ String originalData = "Some data in GZIP";
+
+ // Creating a gzip byte array using GZIPOutputStream
+ byte[] gzipData;
+ try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
+ gzipOutputStream.write(originalData.getBytes(StandardCharsets.UTF_8));
+ gzipOutputStream.close(); // close to flush and finish the compression
+ gzipData = byteArrayOutputStream.toByteArray();
+ }
+
+ // Mocking input stream with the gzip data
+ InputStream gzipStream = new ByteArrayInputStream(gzipData);
+
+ // Call the private method using reflection
+ InputStream resultStream =
+ invokeDetectContentEncodingAndGetInputStream(mockResponse, gzipStream);
+
+ // Decompress and validate the data matches original
+ ByteArrayOutputStream decompressedOutput = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ try (GZIPInputStream gzipInputStream = (GZIPInputStream) resultStream) {
+ while ((bytesRead = gzipInputStream.read(buffer)) != -1) {
+ decompressedOutput.write(buffer, 0, bytesRead);
+ }
+ }
+ String decompressedData = new String(decompressedOutput.toByteArray(), StandardCharsets.UTF_8);
+
+ assertEquals(originalData, decompressedData);
+ }
+
+ @Test
+ public void testDetectContentEncodingAndGetInputStream_Zstd() throws Exception {
+ // Mocking zstd content encoding
+ Header encodingHeader = mock(Header.class);
+ when(encodingHeader.getValue()).thenReturn("zstd");
+ when(mockResponse.getFirstHeader("Content-Encoding")).thenReturn(encodingHeader);
+
+ // Original data to compress and validate
+ String originalData = "Some data in ZSTD";
+
+ // Creating a zstd byte array using ZstdOutputStream
+ byte[] zstdData;
+ try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ ZstdOutputStream zstdOutputStream = new ZstdOutputStream(byteArrayOutputStream)) {
+ zstdOutputStream.write(originalData.getBytes(StandardCharsets.UTF_8));
+ zstdOutputStream.close(); // close to flush and finish the compression
+ zstdData = byteArrayOutputStream.toByteArray();
+ }
+
+ // Mocking input stream with the zstd data
+ InputStream zstdStream = new ByteArrayInputStream(zstdData);
+
+ // Call the private method using reflection
+ InputStream resultStream =
+ invokeDetectContentEncodingAndGetInputStream(mockResponse, zstdStream);
+
+ // Decompress and validate the data matches original
+ ByteArrayOutputStream decompressedOutput = new ByteArrayOutputStream();
+ byte[] buffer = new byte[1024];
+ int bytesRead;
+ try (ZstdInputStream zstdInputStream = (ZstdInputStream) resultStream) {
+ while ((bytesRead = zstdInputStream.read(buffer)) != -1) {
+ decompressedOutput.write(buffer, 0, bytesRead);
+ }
+ }
+ String decompressedData = new String(decompressedOutput.toByteArray(), StandardCharsets.UTF_8);
+
+ assertEquals(originalData, decompressedData);
+ }
+}
diff --git a/thin_public_pom.xml b/thin_public_pom.xml
index 31a1aedee..a781a376d 100644
--- a/thin_public_pom.xml
+++ b/thin_public_pom.xml
@@ -64,6 +64,7 @@
UTF-8
2.0.13
1.6.9
+ 1.5.6-5
@@ -262,6 +263,11 @@
jsoup
${jsoup.version}
+
+ com.github.luben
+ zstd-jni
+ ${zstd-jni.version}
+
org.slf4j
slf4j-api