Repository: housepower/ClickHouse-Native-JDBC
Pull request #454 (2023-10-08 17:49:29)

[FEATURE]: Add IPv6 type. #430

github-actions[bot]: 
<details>
  <summary>BENCHMARK_REPORT</summary>
  <pre style="display:block; white-space:pre-wrap; background-color: #f5f5f5; padding: 10px; border: 1px solid #ccc; border-radius: 4px; font-family: monospace;">
    1. 
  </pre>
</details>

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/454?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#454](https://app.codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/454?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (71ade16) into [master](https://app.codecov.io/gh/housepower/ClickHouse-Native-JDBC/commit/72ff02f4dee64f544db564b7d642650b41bdb2a7?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (72ff02f) will **decrease** coverage by `0.04%`.
> The diff coverage is `48.27%`.

> :exclamation: Current head 71ade16 differs from pull request most recent head 3d25086. Consider uploading reports for the commit 3d25086 to get more accurate results

```diff
@@             Coverage Diff              @@
##             master     #454      +/-   ##
============================================
- Coverage     63.66%   63.63%   -0.04%     
- Complexity     1309     1316       +7     
============================================
  Files           140      141       +1     
  Lines          6815     6844      +29     
  Branches        526      529       +3     
============================================
+ Hits           4339     4355      +16     
- Misses         2209     2220      +11     
- Partials        267      269       +2     
```


| [Files](https://app.codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/454?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [...va/com/github/housepower/data/DataTypeFactory.java](https://app.codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/454?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9kYXRhL0RhdGFUeXBlRmFjdG9yeS5qYXZh) | `88.23% <100.00%> (+0.17%)` | :arrow_up: |
| [...om/github/housepower/jdbc/ClickHouseResultSet.java](https://app.codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/454?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9qZGJjL0NsaWNrSG91c2VSZXN1bHRTZXQuamF2YQ==) | `66.66% <28.57%> (-1.60%)` | :arrow_down: |
| [.../com/github/housepower/data/type/DataTypeIPv6.java](https://app.codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/454?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9kYXRhL3R5cGUvRGF0YVR5cGVJUHY2LmphdmE=) | `52.38% <52.38%> (ø)` | |

... and [1 file with indirect coverage changes](https://app.codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/454/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)


github-actions[bot]: 
<details>
  <summary>BENCHMARK_REPORT</summary>
  <pre style="display:block; white-space:pre-wrap; background-color: #f5f5f5; padding: 10px; border: 1px solid #ccc; border-radius: 4px; font-family: monospace;">
    1. Benchmark                                                  (batchSize)  (columnNum)  (selectNumber)  Mode  Cnt     Score   Error  Units
2. DoubleIBenchmark.benchInsertJdbc                                200000           20             N/A  avgt        300.796          ms/op
3. DoubleIBenchmark.benchInsertJdbc                                200000           50             N/A  avgt        771.911          ms/op
4. DoubleIBenchmark.benchInsertJdbc                                500000           20             N/A  avgt        700.959          ms/op
5. DoubleIBenchmark.benchInsertJdbc                                500000           50             N/A  avgt       1974.523          ms/op
6. DoubleIBenchmark.benchInsertNative                              200000           20             N/A  avgt        479.305          ms/op
7. DoubleIBenchmark.benchInsertNative                              200000           50             N/A  avgt       1226.666          ms/op
8. DoubleIBenchmark.benchInsertNative                              500000           20             N/A  avgt       1115.252          ms/op
9. DoubleIBenchmark.benchInsertNative                              500000           50             N/A  avgt       3222.782          ms/op
10. InsertIBenchmark.benchInsertJdbc                                200000           20             N/A  avgt        205.526          ms/op
11. InsertIBenchmark.benchInsertJdbc                                200000           50             N/A  avgt        204.357          ms/op
12. InsertIBenchmark.benchInsertJdbc                                500000           20             N/A  avgt        407.145          ms/op
13. InsertIBenchmark.benchInsertJdbc                                500000           50             N/A  avgt        420.241          ms/op
14. InsertIBenchmark.benchInsertNative                              200000           20             N/A  avgt        121.482          ms/op
15. InsertIBenchmark.benchInsertNative                              200000           50             N/A  avgt        127.426          ms/op
16. InsertIBenchmark.benchInsertNative                              500000           20             N/A  avgt        291.446          ms/op
17. InsertIBenchmark.benchInsertNative                              500000           50             N/A  avgt        300.729          ms/op
18. IntIBenchmark.benchInsertJdbc                                   200000           20             N/A  avgt        248.016          ms/op
19. IntIBenchmark.benchInsertJdbc                                   200000           50             N/A  avgt        582.227          ms/op
20. IntIBenchmark.benchInsertJdbc                                   500000           20             N/A  avgt        556.841          ms/op
21. IntIBenchmark.benchInsertJdbc                                   500000           50             N/A  avgt       1562.878          ms/op
22. IntIBenchmark.benchInsertNative                                 200000           20             N/A  avgt        414.379          ms/op
23. IntIBenchmark.benchInsertNative                                 200000           50             N/A  avgt       1019.887          ms/op
24. IntIBenchmark.benchInsertNative                                 500000           20             N/A  avgt        937.748          ms/op
25. IntIBenchmark.benchInsertNative                                 500000           50             N/A  avgt       2458.340          ms/op
26. SelectIBenchmark.benchSelectJdbc                                   N/A          N/A          500000  avgt        398.227          ms/op
27. SelectIBenchmark.benchSelectJdbc                                   N/A          N/A        10000000  avgt       7270.778          ms/op
28. SelectIBenchmark.benchSelectNative                                 N/A          N/A          500000  avgt        372.227          ms/op
29. SelectIBenchmark.benchSelectNative                                 N/A          N/A        10000000  avgt       6507.885          ms/op
30. StringIBenchmark.benchInsertJdbc                                200000           20             N/A  avgt        691.199          ms/op
31. StringIBenchmark.benchInsertJdbc                                200000           50             N/A  avgt       1730.641          ms/op
32. StringIBenchmark.benchInsertJdbc                                500000           20             N/A  avgt       1741.297          ms/op
33. StringIBenchmark.benchInsertJdbc                                500000           50             N/A  avgt       4358.536          ms/op
34. StringIBenchmark.benchInsertNative                              200000           20             N/A  avgt        753.686          ms/op
35. StringIBenchmark.benchInsertNative                              200000           50             N/A  avgt       2002.413          ms/op
36. StringIBenchmark.benchInsertNative                              500000           20             N/A  avgt       1945.872          ms/op
37. StringIBenchmark.benchInsertNative                              500000           50             N/A  avgt       4712.858          ms/op
38. WideColumnDoubleInsertIBenchmark.benchInsertJdbc                200000           20             N/A  avgt        288.789          ms/op
39. WideColumnDoubleInsertIBenchmark.benchInsertJdbc                200000           50             N/A  avgt        786.201          ms/op
40. WideColumnDoubleInsertIBenchmark.benchInsertJdbc                500000           20             N/A  avgt        735.862          ms/op
41. WideColumnDoubleInsertIBenchmark.benchInsertJdbc                500000           50             N/A  avgt       1958.457          ms/op
42. WideColumnDoubleInsertIBenchmark.benchInsertNative              200000           20             N/A  avgt        490.371          ms/op
43. WideColumnDoubleInsertIBenchmark.benchInsertNative              200000           50             N/A  avgt       1307.765          ms/op
44. WideColumnDoubleInsertIBenchmark.benchInsertNative              500000           20             N/A  avgt       1131.362          ms/op
45. WideColumnDoubleInsertIBenchmark.benchInsertNative              500000           50             N/A  avgt       3132.334          ms/op
46. WideColumnIntInsertIBenchmark.benchInsertJdbc                   200000           20             N/A  avgt        223.402          ms/op
47. WideColumnIntInsertIBenchmark.benchInsertJdbc                   200000           50             N/A  avgt        548.556          ms/op
48. WideColumnIntInsertIBenchmark.benchInsertJdbc                   500000           20             N/A  avgt        520.219          ms/op
49. WideColumnIntInsertIBenchmark.benchInsertJdbc                   500000           50             N/A  avgt       1455.624          ms/op
50. WideColumnIntInsertIBenchmark.benchInsertNative                 200000           20             N/A  avgt        405.783          ms/op
51. WideColumnIntInsertIBenchmark.benchInsertNative                 200000           50             N/A  avgt       1033.947          ms/op
52. WideColumnIntInsertIBenchmark.benchInsertNative                 500000           20             N/A  avgt        972.578          ms/op
53. WideColumnIntInsertIBenchmark.benchInsertNative                 500000           50             N/A  avgt       2596.243          ms/op
54. WideColumnStringInsertIBenchmark.benchInsertJdbc                200000           20             N/A  avgt        730.240          ms/op
55. WideColumnStringInsertIBenchmark.benchInsertJdbc                200000           50             N/A  avgt       1809.394          ms/op
56. WideColumnStringInsertIBenchmark.benchInsertJdbc                500000           20             N/A  avgt       1799.543          ms/op
57. WideColumnStringInsertIBenchmark.benchInsertJdbc                500000           50             N/A  avgt       4436.635          ms/op
58. WideColumnStringInsertIBenchmark.benchInsertNative              200000           20             N/A  avgt        783.042          ms/op
59. WideColumnStringInsertIBenchmark.benchInsertNative              200000           50             N/A  avgt       1938.079          ms/op
60. WideColumnStringInsertIBenchmark.benchInsertNative              500000           20             N/A  avgt       1885.510          ms/op
61. WideColumnStringInsertIBenchmark.benchInsertNative              500000           50             N/A  avgt       5202.693          ms/op
  </pre>
</details>


Patch:
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/data/DataTypeFactory.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/data/DataTypeFactory.java
index 4f3d6f1..817ccbd 100644
--- a/clickhouse-native-jdbc/src/main/java/com/github/housepower/data/DataTypeFactory.java
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/data/DataTypeFactory.java
@@ -25,6 +25,7 @@ import com.github.housepower.data.type.DataTypeDate32;
 import com.github.housepower.data.type.DataTypeFloat32;
 import com.github.housepower.data.type.DataTypeFloat64;
 import com.github.housepower.data.type.DataTypeIPv4;
+import com.github.housepower.data.type.DataTypeIPv6;
 import com.github.housepower.data.type.DataTypeInt16;
 import com.github.housepower.data.type.DataTypeInt32;
 import com.github.housepower.data.type.DataTypeInt64;
@@ -103,6 +104,7 @@ public class DataTypeFactory {
         Map<String, IDataType<?, ?>> creators = new HashMap<>();
 
         registerType(creators, new DataTypeIPv4());
+        registerType(creators, new DataTypeIPv6());
         registerType(creators, new DataTypeUUID());
         registerType(creators, new DataTypeFloat32());
         registerType(creators, new DataTypeFloat64());
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/data/type/DataTypeIPv6.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/data/type/DataTypeIPv6.java
new file mode 100644
index 0000000..58becbf
--- /dev/null
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/data/type/DataTypeIPv6.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.housepower.data.type;
+
+import com.github.housepower.data.IDataType;
+import com.github.housepower.misc.SQLLexer;
+import com.github.housepower.serde.BinaryDeserializer;
+import com.github.housepower.serde.BinarySerializer;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.sql.SQLException;
+import java.sql.Types;
+
+public class DataTypeIPv6 implements IDataType<BigInteger, BigInteger> {
+
+    @Override
+    public String name() {
+        return "IPv6";
+    }
+
+    @Override
+    public int sqlTypeId() {
+        return Types.BIGINT;
+    }
+
+    @Override
+    public BigInteger defaultValue() {
+        return BigInteger.ZERO;
+    }
+
+    @Override
+    public Class<BigInteger> javaType() {
+        return BigInteger.class;
+    }
+
+    @Override
+    public int getPrecision() {
+        return 0;
+    }
+
+    @Override
+    public int getScale() {
+        return 39;
+    }
+
+    @Override
+    public void serializeBinary(BigInteger data, BinarySerializer serializer) throws SQLException, IOException {
+        byte[] bytes = data.toByteArray();
+        if (bytes.length > 16) {
+            throw new SQLException("IPv6 representation exceeds 16 bytes.");
+        }
+        byte[] paddedBytes = new byte[16];
+        int offset = 16 - bytes.length;
+        System.arraycopy(bytes, 0, paddedBytes, offset, bytes.length);
+        serializer.writeBytes(paddedBytes, 0, paddedBytes.length);
+    }
+
+    @Override
+    public BigInteger deserializeBinary(BinaryDeserializer deserializer) throws SQLException, IOException {
+        byte[] bytes = deserializer.readBytes(16);
+        return new BigInteger(1, bytes);  // force it to be positive
+    }
+    @Override
+    public String[] getAliases() {
+        return new String[0];
+    }
+
+    @Override
+    public BigInteger deserializeText(SQLLexer lexer) throws SQLException {
+        String ipv6String = convertIPv6ToHexadecimalString(lexer.stringLiteral());
+        return new BigInteger(ipv6String, 16);
+    }
+
+    private static String convertIPv6ToHexadecimalString(String ipv6) {
+        return ipv6.replace(":", "");
+    }
+}
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/ClickHouseResultSet.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/ClickHouseResultSet.java
index ba957f5..6623763 100644
--- a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/ClickHouseResultSet.java
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/ClickHouseResultSet.java
@@ -28,6 +28,7 @@ import com.github.housepower.protocol.DataResponse;
 import com.github.housepower.settings.ClickHouseConfig;
 
 import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.sql.*;
@@ -143,6 +144,21 @@ public class ClickHouseResultSet implements SQLResultSet {
         return this.getURL(this.findColumn(name));
     }
 
+    public BigInteger getBigInteger(String columnName) throws SQLException {
+        return getBigInteger(findColumn(columnName));
+    }
+
+    public BigInteger getBigInteger(int columnIndex) throws SQLException {
+        Object valueObj = getObject(columnIndex);
+        if (valueObj instanceof BigInteger) {
+            return (BigInteger) valueObj;
+        }
+        if (wasNull()) {
+            return null;
+        }
+        throw new SQLException("Column " + columnIndex + " is not of type BigInteger.");
+    }
+
     @Override
     public Array getArray(String name) throws SQLException {
         return this.getArray(this.findColumn(name));


Test patch:
diff --git a/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/BooleanTypeITest.java b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/BooleanTypeITest.java
similarity index 95%
rename from clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/BooleanTypeITest.java
rename to clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/BooleanTypeITest.java
index d4dce9e..4d6b8c4 100644
--- a/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/BooleanTypeITest.java
+++ b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/BooleanTypeITest.java
@@ -12,8 +12,9 @@
  * limitations under the License.
  */
 
-package com.github.housepower.jdbc;
+package com.github.housepower.jdbc.type;
 
+import com.github.housepower.jdbc.AbstractITest;
 import com.github.housepower.misc.BytesHelper;
 import org.junit.jupiter.api.Test;
 
diff --git a/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/DecimalTypeITest.java b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/DecimalTypeITest.java
similarity index 97%
rename from clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/DecimalTypeITest.java
rename to clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/DecimalTypeITest.java
index accda7d..25fa908 100644
--- a/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/DecimalTypeITest.java
+++ b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/DecimalTypeITest.java
@@ -12,8 +12,10 @@
  * limitations under the License.
  */
 
-package com.github.housepower.jdbc;
+package com.github.housepower.jdbc.type;
 
+import com.github.housepower.jdbc.AbstractITest;
+import com.github.housepower.jdbc.ClickHouseArray;
 import com.github.housepower.misc.BytesHelper;
 import com.google.common.base.Strings;
 import org.junit.jupiter.api.Test;
diff --git a/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/IPv4TypeITest.java b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/IPv4TypeITest.java
new file mode 100644
index 0000000..b704808
--- /dev/null
+++ b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/IPv4TypeITest.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.housepower.jdbc.type;
+
+import com.github.housepower.jdbc.AbstractITest;
+import com.github.housepower.misc.BytesHelper;
+import org.junit.jupiter.api.Test;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class IPv4TypeITest extends AbstractITest implements BytesHelper {
+
+    @Test
+    public void testIPv4Type() throws Exception {
+        withStatement(statement -> {
+            statement.execute("DROP TABLE IF EXISTS ipv4_test");
+            statement.execute("CREATE TABLE IF NOT EXISTS ipv4_test (value IPv4, nullableValue Nullable(IPv4)) Engine=Memory()");
+
+            Integer rowCnt = 300;
+            Long testIPv4Value1 = ipToLong("192.168.1.1");
+            Long testIPv4Value2 = ipToLong("127.0.0.1");
+
+            try (PreparedStatement pstmt = statement.getConnection().prepareStatement(
+                    "INSERT INTO ipv4_test (value, nullableValue) values(?, ?);")) {
+                for (int i = 0; i < rowCnt; i++) {
+                    pstmt.setLong(1, testIPv4Value1);
+                    pstmt.setLong(2, testIPv4Value2);
+                    pstmt.addBatch();
+                }
+                pstmt.executeBatch();
+            }
+
+            ResultSet rs = statement.executeQuery("SELECT * FROM ipv4_test;");
+            int size = 0;
+            while (rs.next()) {
+                size++;
+                Long value = rs.getLong(1);
+                assertEquals(value, testIPv4Value1);
+                Long nullableValue = rs.getLong(2);
+                assertEquals(nullableValue, testIPv4Value2);
+            }
+
+            assertEquals(size, (int) rowCnt);
+
+            statement.execute("DROP TABLE IF EXISTS ipv4_test");
+        });
+    }
+
+    public long ipToLong(String ipAddress) {
+        String[] ipAddressInArray = ipAddress.split("\\.");
+
+        long result = 0;
+        for (int i = 0; i < ipAddressInArray.length; i++) {
+            int power = 3 - i;
+            int ip = Integer.parseInt(ipAddressInArray[i]);
+            result += ip * Math.pow(256, power);
+        }
+
+        return result;
+    }
+
+}
diff --git a/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/IPv6TypeITest.java b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/IPv6TypeITest.java
new file mode 100644
index 0000000..1ff3277
--- /dev/null
+++ b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/IPv6TypeITest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.housepower.jdbc.type;
+
+import com.github.housepower.jdbc.AbstractITest;
+import com.github.housepower.jdbc.ClickHouseResultSet;
+import com.github.housepower.misc.BytesHelper;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigInteger;
+import java.sql.PreparedStatement;
+import java.sql.Types;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+public class IPv6TypeITest extends AbstractITest implements BytesHelper {
+
+    @Test
+    public void testIPv6Type() throws Exception {
+        withStatement(statement -> {
+            statement.execute("DROP TABLE IF EXISTS ipv6_test");
+            statement.execute("CREATE TABLE IF NOT EXISTS ipv6_test (value IPv6, nullableValue Nullable(IPv6)) Engine=Memory()");
+
+            Integer rowCnt = 300;
+
+            BigInteger testIPv6Value1 = new BigInteger("20010db885a3000000008a2e03707334", 16);
+            BigInteger testIPv6Value2 = new BigInteger("1", 16);
+
+            try (PreparedStatement pstmt = statement.getConnection().prepareStatement(
+                    "INSERT INTO ipv6_test (value, nullableValue) values(?, ?);")) {
+                for (int i = 0; i < rowCnt; i++) {
+                    pstmt.setObject(1, testIPv6Value1, Types.BIGINT);
+                    pstmt.setObject(2, testIPv6Value2, Types.BIGINT);
+                    pstmt.addBatch();
+                }
+                pstmt.executeBatch();
+            }
+
+            ClickHouseResultSet rs = (ClickHouseResultSet) statement.executeQuery("SELECT * FROM ipv6_test;");
+            int size = 0;
+            while (rs.next()) {
+                size++;
+                BigInteger value = rs.getBigInteger(1);
+                assertEquals(value, testIPv6Value1);
+                BigInteger nullableValue = rs.getBigInteger(2);
+                assertEquals(nullableValue, testIPv6Value2);
+            }
+
+            assertEquals(size, (int) rowCnt);
+
+            statement.execute("DROP TABLE IF EXISTS ipv6_test");
+        });
+    }
+
+}
diff --git a/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/LowCardinalityTypeTest.java b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/LowCardinalityTypeTest.java
similarity index 98%
rename from clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/LowCardinalityTypeTest.java
rename to clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/LowCardinalityTypeTest.java
index b36aa80..e9cff35 100644
--- a/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/LowCardinalityTypeTest.java
+++ b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/type/LowCardinalityTypeTest.java
@@ -12,8 +12,9 @@
  * limitations under the License.
  */
 
-package com.github.housepower.jdbc;
+package com.github.housepower.jdbc.type;
 
+import com.github.housepower.jdbc.AbstractITest;
 import com.github.housepower.misc.BytesHelper;
 import org.junit.jupiter.api.Test;