Repository: housepower/ClickHouse-Native-JDBC
Pull request #284 (2021-01-05 16:38:50)

Rename Either to Switcher and reintroduce scala style Either, Left, Right

pan3793: Benchmark Report
===
```

```
pan3793: Benchmark Report
===
```
Benchmark                                           (batchSize)  (columnNum)  (selectNumber)  Mode  Cnt      Score   Error  Units
InsertIBenchmark.benchInsertHttp                         200000           20             N/A  avgt         419.192          ms/op
InsertIBenchmark.benchInsertHttp                         200000           50             N/A  avgt         404.106          ms/op
InsertIBenchmark.benchInsertHttp                         500000           20             N/A  avgt        1062.896          ms/op
InsertIBenchmark.benchInsertHttp                         500000           50             N/A  avgt        1067.277          ms/op
InsertIBenchmark.benchInsertNative                       200000           20             N/A  avgt         107.858          ms/op
InsertIBenchmark.benchInsertNative                       200000           50             N/A  avgt          93.262          ms/op
InsertIBenchmark.benchInsertNative                       500000           20             N/A  avgt         205.939          ms/op
InsertIBenchmark.benchInsertNative                       500000           50             N/A  avgt         216.711          ms/op
RowBinaryDoubleIBenchmark.benchInsertHttpRowBinary       200000           20             N/A  avgt         265.850          ms/op
RowBinaryDoubleIBenchmark.benchInsertHttpRowBinary       200000           50             N/A  avgt         682.893          ms/op
RowBinaryDoubleIBenchmark.benchInsertHttpRowBinary       500000           20             N/A  avgt         536.784          ms/op
RowBinaryDoubleIBenchmark.benchInsertHttpRowBinary       500000           50             N/A  avgt        1539.153          ms/op
RowBinaryDoubleIBenchmark.benchInsertNative              200000           20             N/A  avgt         492.122          ms/op
RowBinaryDoubleIBenchmark.benchInsertNative              200000           50             N/A  avgt        1368.767          ms/op
RowBinaryDoubleIBenchmark.benchInsertNative              500000           20             N/A  avgt        1163.910          ms/op
RowBinaryDoubleIBenchmark.benchInsertNative              500000           50             N/A  avgt        3144.033          ms/op
RowBinaryIntIBenchmark.benchInsertHttpRowBinary          200000           20             N/A  avgt         204.639          ms/op
RowBinaryIntIBenchmark.benchInsertHttpRowBinary          200000           50             N/A  avgt         540.565          ms/op
RowBinaryIntIBenchmark.benchInsertHttpRowBinary          500000           20             N/A  avgt         455.492          ms/op
RowBinaryIntIBenchmark.benchInsertHttpRowBinary          500000           50             N/A  avgt        1529.345          ms/op
RowBinaryIntIBenchmark.benchInsertNative                 200000           20             N/A  avgt         263.416          ms/op
RowBinaryIntIBenchmark.benchInsertNative                 200000           50             N/A  avgt         809.574          ms/op
RowBinaryIntIBenchmark.benchInsertNative                 500000           20             N/A  avgt         769.754          ms/op
RowBinaryIntIBenchmark.benchInsertNative                 500000           50             N/A  avgt        1901.319          ms/op
RowBinaryStringIBenchmark.benchInsertHttpRowBinary       200000           20             N/A  avgt         505.022          ms/op
RowBinaryStringIBenchmark.benchInsertHttpRowBinary       200000           50             N/A  avgt        1256.586          ms/op
RowBinaryStringIBenchmark.benchInsertHttpRowBinary       500000           20             N/A  avgt        1256.067          ms/op
RowBinaryStringIBenchmark.benchInsertHttpRowBinary       500000           50             N/A  avgt        2891.172          ms/op
RowBinaryStringIBenchmark.benchInsertNative              200000           20             N/A  avgt         634.897          ms/op
RowBinaryStringIBenchmark.benchInsertNative              200000           50             N/A  avgt        1727.370          ms/op
RowBinaryStringIBenchmark.benchInsertNative              500000           20             N/A  avgt        1596.298          ms/op
RowBinaryStringIBenchmark.benchInsertNative              500000           50             N/A  avgt        4350.538          ms/op
SelectIBenchmark.benchSelectHTTP                            N/A          N/A          500000  avgt        1350.084          ms/op
SelectIBenchmark.benchSelectHTTP                            N/A          N/A        10000000  avgt       26839.644          ms/op
SelectIBenchmark.benchSelectNative                          N/A          N/A          500000  avgt         282.801          ms/op
SelectIBenchmark.benchSelectNative                          N/A          N/A        10000000  avgt        5595.441          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertHttp         200000           20             N/A  avgt         923.015          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertHttp         200000           50             N/A  avgt        2413.325          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertHttp         500000           20             N/A  avgt        2299.884          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertHttp         500000           50             N/A  avgt        5947.322          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertNative       200000           20             N/A  avgt         464.444          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertNative       200000           50             N/A  avgt        1271.419          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertNative       500000           20             N/A  avgt        1123.411          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertNative       500000           50             N/A  avgt        3056.810          ms/op
WideColumnIntInsertIBenchmark.benchInsertHttp            200000           20             N/A  avgt         459.780          ms/op
WideColumnIntInsertIBenchmark.benchInsertHttp            200000           50             N/A  avgt        1191.579          ms/op
WideColumnIntInsertIBenchmark.benchInsertHttp            500000           20             N/A  avgt        1196.002          ms/op
WideColumnIntInsertIBenchmark.benchInsertHttp            500000           50             N/A  avgt        2912.112          ms/op
WideColumnIntInsertIBenchmark.benchInsertNative          200000           20             N/A  avgt         306.343          ms/op
WideColumnIntInsertIBenchmark.benchInsertNative          200000           50             N/A  avgt         703.978          ms/op
WideColumnIntInsertIBenchmark.benchInsertNative          500000           20             N/A  avgt         728.942          ms/op
WideColumnIntInsertIBenchmark.benchInsertNative          500000           50             N/A  avgt        1711.511          ms/op
WideColumnStringInsertIBenchmark.benchInsertHttp         200000           20             N/A  avgt         576.711          ms/op
WideColumnStringInsertIBenchmark.benchInsertHttp         200000           50             N/A  avgt        1413.399          ms/op
WideColumnStringInsertIBenchmark.benchInsertHttp         500000           20             N/A  avgt        1485.759          ms/op
WideColumnStringInsertIBenchmark.benchInsertHttp         500000           50             N/A  avgt        3502.782          ms/op
WideColumnStringInsertIBenchmark.benchInsertNative       200000           20             N/A  avgt         671.638          ms/op
WideColumnStringInsertIBenchmark.benchInsertNative       200000           50             N/A  avgt        1729.257          ms/op
WideColumnStringInsertIBenchmark.benchInsertNative       500000           20             N/A  avgt        1549.425          ms/op
WideColumnStringInsertIBenchmark.benchInsertNative       500000           50             N/A  avgt        3795.703          ms/op
```
codecov[bot]: # [Codecov](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284?src=pr&el=h1) Report
> Merging [#284](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284?src=pr&el=desc) (7a76d4d) into [master](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/commit/281f1ee108acadf81553ee3773ce984594f09dd2?el=desc) (281f1ee) will **increase** coverage by `0.06%`.
> The diff coverage is `90.90%`.

[![Impacted file tree graph](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/graphs/tree.svg?width=650&height=150&src=pr&token=Izz9Qy1I72)](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284?src=pr&el=tree)

```diff
@@             Coverage Diff              @@
##             master     #284      +/-   ##
============================================
+ Coverage     59.75%   59.82%   +0.06%     
- Complexity     1166     1180      +14     
============================================
  Files           111      115       +4     
  Lines          5685     5717      +32     
  Branches        445      446       +1     
============================================
+ Hits           3397     3420      +23     
- Misses         2054     2060       +6     
- Partials        234      237       +3     
```


| [Impacted Files](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284?src=pr&el=tree) | Coverage Δ | Complexity Δ | |
|---|---|---|---|
| [...m/github/housepower/jdbc/connect/NativeClient.java](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/diff?src=pr&el=tree#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9qZGJjL2Nvbm5lY3QvTmF0aXZlQ2xpZW50LmphdmE=) | `73.33% <ø> (ø)` | `17.00 <0.00> (ø)` | |
| [...ower/jdbc/exception/InvalidOperationException.java](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/diff?src=pr&el=tree#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9qZGJjL2V4Y2VwdGlvbi9JbnZhbGlkT3BlcmF0aW9uRXhjZXB0aW9uLmphdmE=) | `33.33% <33.33%> (ø)` | `1.00 <1.00> (?)` | |
| [...ain/java/com/github/housepower/jdbc/misc/Left.java](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/diff?src=pr&el=tree#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9qZGJjL21pc2MvTGVmdC5qYXZh) | `88.88% <88.88%> (ø)` | `6.00 <6.00> (?)` | |
| [...in/java/com/github/housepower/jdbc/misc/Right.java](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/diff?src=pr&el=tree#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9qZGJjL21pc2MvUmlnaHQuamF2YQ==) | `88.88% <88.88%> (ø)` | `6.00 <6.00> (?)` | |
| [...thub/housepower/jdbc/serde/BinaryDeserializer.java](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/diff?src=pr&el=tree#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9qZGJjL3NlcmRlL0JpbmFyeURlc2VyaWFsaXplci5qYXZh) | `93.10% <92.85%> (-4.98%)` | `17.00 <9.00> (ø)` | |
| [...github/housepower/jdbc/serde/BinarySerializer.java](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/diff?src=pr&el=tree#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9qZGJjL3NlcmRlL0JpbmFyeVNlcmlhbGl6ZXIuamF2YQ==) | `94.20% <97.05%> (ø)` | `20.00 <7.00> (ø)` | |
| [...n/java/com/github/housepower/jdbc/misc/Either.java](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/diff?src=pr&el=tree#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9qZGJjL21pc2MvRWl0aGVyLmphdmE=) | `100.00% <100.00%> (ø)` | `2.00 <2.00> (-3.00)` | |
| [...java/com/github/housepower/jdbc/misc/Switcher.java](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/diff?src=pr&el=tree#diff-Y2xpY2tob3VzZS1uYXRpdmUtamRiYy9zcmMvbWFpbi9qYXZhL2NvbS9naXRodWIvaG91c2Vwb3dlci9qZGJjL21pc2MvU3dpdGNoZXIuamF2YQ==) | `100.00% <100.00%> (ø)` | `4.00 <4.00> (?)` | |
| ... and [2 more](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284?src=pr&el=footer). Last update [281f1ee...9c59228](https://codecov.io/gh/housepower/ClickHouse-Native-JDBC/pull/284?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

pan3793: Benchmark Report
===
```
Benchmark                                           (batchSize)  (columnNum)  (selectNumber)  Mode  Cnt      Score   Error  Units
InsertIBenchmark.benchInsertHttp                         200000           20             N/A  avgt         410.724          ms/op
InsertIBenchmark.benchInsertHttp                         200000           50             N/A  avgt         402.284          ms/op
InsertIBenchmark.benchInsertHttp                         500000           20             N/A  avgt        1022.998          ms/op
InsertIBenchmark.benchInsertHttp                         500000           50             N/A  avgt        1075.904          ms/op
InsertIBenchmark.benchInsertNative                       200000           20             N/A  avgt         101.218          ms/op
InsertIBenchmark.benchInsertNative                       200000           50             N/A  avgt          94.455          ms/op
InsertIBenchmark.benchInsertNative                       500000           20             N/A  avgt         189.818          ms/op
InsertIBenchmark.benchInsertNative                       500000           50             N/A  avgt         210.263          ms/op
RowBinaryDoubleIBenchmark.benchInsertHttpRowBinary       200000           20             N/A  avgt         253.560          ms/op
RowBinaryDoubleIBenchmark.benchInsertHttpRowBinary       200000           50             N/A  avgt         683.110          ms/op
RowBinaryDoubleIBenchmark.benchInsertHttpRowBinary       500000           20             N/A  avgt         537.621          ms/op
RowBinaryDoubleIBenchmark.benchInsertHttpRowBinary       500000           50             N/A  avgt        1595.511          ms/op
RowBinaryDoubleIBenchmark.benchInsertNative              200000           20             N/A  avgt         387.022          ms/op
RowBinaryDoubleIBenchmark.benchInsertNative              200000           50             N/A  avgt        1106.727          ms/op
RowBinaryDoubleIBenchmark.benchInsertNative              500000           20             N/A  avgt         919.828          ms/op
RowBinaryDoubleIBenchmark.benchInsertNative              500000           50             N/A  avgt        2737.442          ms/op
RowBinaryIntIBenchmark.benchInsertHttpRowBinary          200000           20             N/A  avgt         197.922          ms/op
RowBinaryIntIBenchmark.benchInsertHttpRowBinary          200000           50             N/A  avgt         516.439          ms/op
RowBinaryIntIBenchmark.benchInsertHttpRowBinary          500000           20             N/A  avgt         463.241          ms/op
RowBinaryIntIBenchmark.benchInsertHttpRowBinary          500000           50             N/A  avgt        1540.699          ms/op
RowBinaryIntIBenchmark.benchInsertNative                 200000           20             N/A  avgt         260.867          ms/op
RowBinaryIntIBenchmark.benchInsertNative                 200000           50             N/A  avgt         601.203          ms/op
RowBinaryIntIBenchmark.benchInsertNative                 500000           20             N/A  avgt         520.497          ms/op
RowBinaryIntIBenchmark.benchInsertNative                 500000           50             N/A  avgt        1657.376          ms/op
RowBinaryStringIBenchmark.benchInsertHttpRowBinary       200000           20             N/A  avgt         502.828          ms/op
RowBinaryStringIBenchmark.benchInsertHttpRowBinary       200000           50             N/A  avgt        1217.659          ms/op
RowBinaryStringIBenchmark.benchInsertHttpRowBinary       500000           20             N/A  avgt        1179.887          ms/op
RowBinaryStringIBenchmark.benchInsertHttpRowBinary       500000           50             N/A  avgt        3049.014          ms/op
RowBinaryStringIBenchmark.benchInsertNative              200000           20             N/A  avgt         574.462          ms/op
RowBinaryStringIBenchmark.benchInsertNative              200000           50             N/A  avgt        1509.267          ms/op
RowBinaryStringIBenchmark.benchInsertNative              500000           20             N/A  avgt        1393.404          ms/op
RowBinaryStringIBenchmark.benchInsertNative              500000           50             N/A  avgt        3615.893          ms/op
SelectIBenchmark.benchSelectHTTP                            N/A          N/A          500000  avgt        1223.213          ms/op
SelectIBenchmark.benchSelectHTTP                            N/A          N/A        10000000  avgt       26147.019          ms/op
SelectIBenchmark.benchSelectNative                          N/A          N/A          500000  avgt         289.841          ms/op
SelectIBenchmark.benchSelectNative                          N/A          N/A        10000000  avgt        5312.388          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertHttp         200000           20             N/A  avgt         911.791          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertHttp         200000           50             N/A  avgt        2407.457          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertHttp         500000           20             N/A  avgt        2267.668          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertHttp         500000           50             N/A  avgt        5952.624          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertNative       200000           20             N/A  avgt         382.845          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertNative       200000           50             N/A  avgt        1186.001          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertNative       500000           20             N/A  avgt         936.108          ms/op
WideColumnDoubleInsertIBenchmark.benchInsertNative       500000           50             N/A  avgt        2756.035          ms/op
WideColumnIntInsertIBenchmark.benchInsertHttp            200000           20             N/A  avgt         459.451          ms/op
WideColumnIntInsertIBenchmark.benchInsertHttp            200000           50             N/A  avgt        1173.660          ms/op
WideColumnIntInsertIBenchmark.benchInsertHttp            500000           20             N/A  avgt        1219.355          ms/op
WideColumnIntInsertIBenchmark.benchInsertHttp            500000           50             N/A  avgt        3087.139          ms/op
WideColumnIntInsertIBenchmark.benchInsertNative          200000           20             N/A  avgt         264.833          ms/op
WideColumnIntInsertIBenchmark.benchInsertNative          200000           50             N/A  avgt         641.523          ms/op
WideColumnIntInsertIBenchmark.benchInsertNative          500000           20             N/A  avgt         624.005          ms/op
WideColumnIntInsertIBenchmark.benchInsertNative          500000           50             N/A  avgt        1553.175          ms/op
WideColumnStringInsertIBenchmark.benchInsertHttp         200000           20             N/A  avgt         618.271          ms/op
WideColumnStringInsertIBenchmark.benchInsertHttp         200000           50             N/A  avgt        1486.843          ms/op
WideColumnStringInsertIBenchmark.benchInsertHttp         500000           20             N/A  avgt        1540.905          ms/op
WideColumnStringInsertIBenchmark.benchInsertHttp         500000           50             N/A  avgt        3700.452          ms/op
WideColumnStringInsertIBenchmark.benchInsertNative       200000           20             N/A  avgt         605.889          ms/op
WideColumnStringInsertIBenchmark.benchInsertNative       200000           50             N/A  avgt        1539.707          ms/op
WideColumnStringInsertIBenchmark.benchInsertNative       500000           20             N/A  avgt        1456.742          ms/op
WideColumnStringInsertIBenchmark.benchInsertNative       500000           50             N/A  avgt        3766.768          ms/op
```

Patch:
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/connect/NativeClient.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/connect/NativeClient.java
index 2447c1d..84b8acb 100644
--- a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/connect/NativeClient.java
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/connect/NativeClient.java
@@ -56,7 +56,7 @@ public class NativeClient {
 
             return new NativeClient(socket,
                     new BinarySerializer(new SocketBuffedWriter(socket), true),
-                    new BinaryDeserializer(new SocketBuffedReader(socket)));
+                    new BinaryDeserializer(new SocketBuffedReader(socket), true));
         } catch (IOException ex) {
             throw new SQLException(ex.getMessage(), ex);
         }
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/exception/InvalidOperationException.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/exception/InvalidOperationException.java
new file mode 100644
index 0000000..f2fc42a
--- /dev/null
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/exception/InvalidOperationException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.exception;
+
+public class InvalidOperationException extends ClickHouseException {
+
+    public InvalidOperationException(String message) {
+        super(message);
+    }
+
+    public InvalidOperationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public InvalidOperationException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Either.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Either.java
index 03d1e52..d2076d0 100644
--- a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Either.java
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Either.java
@@ -14,22 +14,25 @@
 
 package com.github.housepower.jdbc.misc;
 
-public class Either<T> {
-    private final T left;
-    private final T right;
+import java.util.function.Function;
 
-    private boolean isLeft = true;
+public interface Either<L, R> {
 
-    public Either(T left, T right) {
-        this.left = left;
-        this.right = right;
+    static <L1, R1> Either<L1, R1> left(L1 value) {
+        return new Left<>(value);
     }
 
-    public void select(boolean isRight) {
-        isLeft = !isRight;
+    static <L1, R1> Either<L1, R1> right(R1 value) {
+        return new Right<>(value);
     }
 
-    public T get() {
-        return isLeft ? left : right;
-    }
+    boolean isRight();
+
+    <R1> Either<L, R1> map(Function<R, R1> f);
+
+    <R1> Either<L, R1> flatMap(Function<R, Either<L, R1>> f);
+
+    L getLeft();
+
+    R getRight();
 }
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Left.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Left.java
new file mode 100644
index 0000000..e1e8ece
--- /dev/null
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Left.java
@@ -0,0 +1,59 @@
+/*
+ * 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.misc;
+
+import com.github.housepower.jdbc.exception.InvalidOperationException;
+
+import java.util.Locale;
+import java.util.function.Function;
+
+public class Left<L, R> implements Either<L, R> {
+
+    private final L value;
+
+    Left(L value) {
+        this.value = value;
+    }
+
+    @Override
+    public boolean isRight() {
+        return false;
+    }
+
+    @Override
+    public <R1> Either<L, R1> map(Function<R, R1> f) {
+        return Either.left(value);
+    }
+
+    @Override
+    public <R1> Either<L, R1> flatMap(Function<R, Either<L, R1>> f) {
+        return Either.left(value);
+    }
+
+    @Override
+    public L getLeft() {
+        return value;
+    }
+
+    @Override
+    public R getRight() {
+        throw new InvalidOperationException("Left not support #getRight");
+    }
+
+    @Override
+    public String toString() {
+        return String.format(Locale.ROOT, "Left(%s)", value);
+    }
+}
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Right.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Right.java
new file mode 100644
index 0000000..c77ce3c
--- /dev/null
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Right.java
@@ -0,0 +1,59 @@
+/*
+ * 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.misc;
+
+import com.github.housepower.jdbc.exception.InvalidOperationException;
+
+import java.util.Locale;
+import java.util.function.Function;
+
+public class Right<L, R> implements Either<L, R> {
+
+    private final R value;
+
+    Right(R value) {
+        this.value = value;
+    }
+
+    @Override
+    public boolean isRight() {
+        return true;
+    }
+
+    @Override
+    public <R1> Either<L, R1> map(Function<R, R1> f) {
+        return Either.right(f.apply(value));
+    }
+
+    @Override
+    public <R1> Either<L, R1> flatMap(Function<R, Either<L, R1>> f) {
+        return f.apply(value);
+    }
+
+    @Override
+    public L getLeft() {
+        throw new InvalidOperationException("Right not support #getLeft");
+    }
+
+    @Override
+    public R getRight() {
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        return String.format(Locale.ROOT, "Right(%s)", value);
+    }
+}
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Switcher.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Switcher.java
new file mode 100644
index 0000000..0dacf16
--- /dev/null
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/misc/Switcher.java
@@ -0,0 +1,35 @@
+/*
+ * 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.misc;
+
+public class Switcher<T> {
+    private final T left;
+    private final T right;
+
+    private boolean isRight = true;
+
+    public Switcher(T left, T right) {
+        this.left = left;
+        this.right = right;
+    }
+
+    public void select(boolean isRight) {
+        this.isRight = isRight;
+    }
+
+    public T get() {
+        return this.isRight ? right : left;
+    }
+}
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/serde/BinaryDeserializer.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/serde/BinaryDeserializer.java
index a5d6842..fb863cd 100644
--- a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/serde/BinaryDeserializer.java
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/serde/BinaryDeserializer.java
@@ -16,23 +16,29 @@ package com.github.housepower.jdbc.serde;
 
 import com.github.housepower.jdbc.buffer.BuffedReader;
 import com.github.housepower.jdbc.buffer.CompressedBuffedReader;
-import com.github.housepower.jdbc.misc.Either;
+import com.github.housepower.jdbc.misc.Switcher;
 
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 
 public class BinaryDeserializer {
 
-    private final Either<BuffedReader> either;
+    private final Switcher<BuffedReader> switcher;
+    private final boolean enableCompress;
 
-    public BinaryDeserializer(BuffedReader buffedReader) {
-        either = new Either<>(buffedReader, new CompressedBuffedReader(buffedReader));
+    public BinaryDeserializer(BuffedReader buffedReader, boolean enableCompress) {
+        this.enableCompress = enableCompress;
+        BuffedReader compressedReader = null;
+        if (enableCompress) {
+            compressedReader = new CompressedBuffedReader(buffedReader);
+        }
+        switcher = new Switcher<>(compressedReader, buffedReader);
     }
 
     public long readVarInt() throws IOException {
         int number = 0;
         for (int i = 0; i < 9; i++) {
-            int byt = either.get().readBinary();
+            int byt = switcher.get().readBinary();
 
             number |= (byt & 0x7F) << (7 * i);
 
@@ -46,70 +52,74 @@ public class BinaryDeserializer {
     @SuppressWarnings("PointlessBitwiseExpression")
     public short readShort() throws IOException {
         // @formatter:off
-        return (short) (((either.get().readBinary() & 0xFF) << 0)
-                      + ((either.get().readBinary() & 0xFF) << 8));
+        return (short) (((switcher.get().readBinary() & 0xFF) << 0)
+                      + ((switcher.get().readBinary() & 0xFF) << 8));
         // @formatter:on
     }
 
     @SuppressWarnings("PointlessBitwiseExpression")
     public int readInt() throws IOException {
         // @formatter:off
-        return ((either.get().readBinary() & 0xFF) << 0)
-             + ((either.get().readBinary() & 0xFF) << 8)
-             + ((either.get().readBinary() & 0xFF) << 16)
-             + ((either.get().readBinary() & 0xFF) << 24);
+        return ((switcher.get().readBinary() & 0xFF) << 0)
+             + ((switcher.get().readBinary() & 0xFF) << 8)
+             + ((switcher.get().readBinary() & 0xFF) << 16)
+             + ((switcher.get().readBinary() & 0xFF) << 24);
         // @formatter:on
     }
 
     @SuppressWarnings("PointlessBitwiseExpression")
     public long readLong() throws IOException {
         // @formatter:off
-        return ((either.get().readBinary() & 0xFFL) << 0)
-             + ((either.get().readBinary() & 0xFFL) << 8)
-             + ((either.get().readBinary() & 0xFFL) << 16)
-             + ((either.get().readBinary() & 0xFFL) << 24)
-             + ((either.get().readBinary() & 0xFFL) << 32)
-             + ((either.get().readBinary() & 0xFFL) << 40)
-             + ((either.get().readBinary() & 0xFFL) << 48)
-             + ((either.get().readBinary() & 0xFFL) << 56);
+        return ((switcher.get().readBinary() & 0xFFL) << 0)
+             + ((switcher.get().readBinary() & 0xFFL) << 8)
+             + ((switcher.get().readBinary() & 0xFFL) << 16)
+             + ((switcher.get().readBinary() & 0xFFL) << 24)
+             + ((switcher.get().readBinary() & 0xFFL) << 32)
+             + ((switcher.get().readBinary() & 0xFFL) << 40)
+             + ((switcher.get().readBinary() & 0xFFL) << 48)
+             + ((switcher.get().readBinary() & 0xFFL) << 56);
         // @formatter:on
     }
 
     public boolean readBoolean() throws IOException {
-        return (either.get().readBinary() != 0);
+        return (switcher.get().readBinary() != 0);
     }
 
     public byte[] readBytesBinary() throws IOException {
         byte[] data = new byte[(int) readVarInt()];
-        either.get().readBinary(data);
+        switcher.get().readBinary(data);
         return data;
     }
 
     public String readUTF8StringBinary() throws IOException {
         byte[] data = new byte[(int) readVarInt()];
-        return either.get().readBinary(data) > 0 ? new String(data, StandardCharsets.UTF_8) : "";
+        return switcher.get().readBinary(data) > 0 ? new String(data, StandardCharsets.UTF_8) : "";
     }
 
     public byte readByte() throws IOException {
-        return (byte) either.get().readBinary();
+        return (byte) switcher.get().readBinary();
     }
 
     public void maybeEnableCompressed() {
-        either.select(true);
+        if (enableCompress) {
+            switcher.select(false);
+        }
     }
 
     public void maybeDisableCompressed() {
-        either.select(false);
+        if (enableCompress) {
+            switcher.select(true);
+        }
     }
 
     @SuppressWarnings("PointlessBitwiseExpression")
     public float readFloat() throws IOException {
         // @formatter:off
         return Float.intBitsToFloat(
-               ((either.get().readBinary() & 0xFF) << 0)
-             + ((either.get().readBinary() & 0xFF) << 8)
-             + ((either.get().readBinary() & 0xFF) << 16)
-             + ((either.get().readBinary()       ) << 24));
+               ((switcher.get().readBinary() & 0xFF) << 0)
+             + ((switcher.get().readBinary() & 0xFF) << 8)
+             + ((switcher.get().readBinary() & 0xFF) << 16)
+             + ((switcher.get().readBinary()       ) << 24));
         // @formatter:on
     }
 
@@ -117,21 +127,21 @@ public class BinaryDeserializer {
     public double readDouble() throws IOException {
         // @formatter:off
         return Double.longBitsToDouble(
-                ((either.get().readBinary() & 0xFFL) << 0 )
-              + ((either.get().readBinary() & 0xFFL) << 8 )
-              + ((either.get().readBinary() & 0xFFL) << 16)
-              + ((either.get().readBinary() & 0xFFL) << 24)
-              + ((either.get().readBinary() & 0xFFL) << 32)
-              + ((either.get().readBinary() & 0xFFL) << 40)
-              + ((either.get().readBinary() & 0xFFL) << 48)
-              + ((either.get().readBinary() & 0xFFL) << 56)
+                ((switcher.get().readBinary() & 0xFFL) << 0 )
+              + ((switcher.get().readBinary() & 0xFFL) << 8 )
+              + ((switcher.get().readBinary() & 0xFFL) << 16)
+              + ((switcher.get().readBinary() & 0xFFL) << 24)
+              + ((switcher.get().readBinary() & 0xFFL) << 32)
+              + ((switcher.get().readBinary() & 0xFFL) << 40)
+              + ((switcher.get().readBinary() & 0xFFL) << 48)
+              + ((switcher.get().readBinary() & 0xFFL) << 56)
         );
         // @formatter:on
     }
 
     public byte[] readBytes(int size) throws IOException {
         byte[] bytes = new byte[size];
-        either.get().readBinary(bytes);
+        switcher.get().readBinary(bytes);
         return bytes;
     }
 }
diff --git a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/serde/BinarySerializer.java b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/serde/BinarySerializer.java
index ea32b02..b6a306d 100644
--- a/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/serde/BinarySerializer.java
+++ b/clickhouse-native-jdbc/src/main/java/com/github/housepower/jdbc/serde/BinarySerializer.java
@@ -16,7 +16,7 @@ package com.github.housepower.jdbc.serde;
 
 import com.github.housepower.jdbc.buffer.BuffedWriter;
 import com.github.housepower.jdbc.buffer.CompressedBuffedWriter;
-import com.github.housepower.jdbc.misc.Either;
+import com.github.housepower.jdbc.misc.Switcher;
 import com.github.housepower.jdbc.settings.ClickHouseDefines;
 
 import java.io.IOException;
@@ -25,16 +25,16 @@ import java.nio.charset.StandardCharsets;
 
 public class BinarySerializer {
 
-    private final Either<BuffedWriter> either;
+    private final Switcher<BuffedWriter> switcher;
     private final boolean enableCompress;
 
     public BinarySerializer(BuffedWriter writer, boolean enableCompress) {
         this.enableCompress = enableCompress;
-        BuffedWriter compressBuffer = null;
+        BuffedWriter compressWriter = null;
         if (enableCompress) {
-            compressBuffer = new CompressedBuffedWriter(ClickHouseDefines.SOCKET_SEND_BUFFER_BYTES, writer);
+            compressWriter = new CompressedBuffedWriter(ClickHouseDefines.SOCKET_SEND_BUFFER_BYTES, writer);
         }
-        either = new Either<>(writer, compressBuffer);
+        switcher = new Switcher<>(compressWriter, writer);
     }
 
     public void writeVarInt(long x) throws IOException {
@@ -46,7 +46,7 @@ public class BinarySerializer {
             }
 
             x >>= 7;
-            either.get().writeBinary(byt);
+            switcher.get().writeBinary(byt);
 
             if (x == 0) {
                 return;
@@ -55,7 +55,7 @@ public class BinarySerializer {
     }
 
     public void writeByte(byte x) throws IOException {
-        either.get().writeBinary(x);
+        switcher.get().writeBinary(x);
     }
 
     public void writeBoolean(boolean x) throws IOException {
@@ -65,32 +65,32 @@ public class BinarySerializer {
     @SuppressWarnings("PointlessBitwiseExpression")
     public void writeShort(short i) throws IOException {
         // @formatter:off
-        either.get().writeBinary((byte) ((i >> 0) & 0xFF));
-        either.get().writeBinary((byte) ((i >> 8) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 0) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 8) & 0xFF));
         // @formatter:on
     }
 
     @SuppressWarnings("PointlessBitwiseExpression")
     public void writeInt(int i) throws IOException {
         // @formatter:off
-        either.get().writeBinary((byte) ((i >> 0)  & 0xFF));
-        either.get().writeBinary((byte) ((i >> 8)  & 0xFF));
-        either.get().writeBinary((byte) ((i >> 16) & 0xFF));
-        either.get().writeBinary((byte) ((i >> 24) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 0)  & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 8)  & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 16) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 24) & 0xFF));
         // @formatter:on
     }
 
     @SuppressWarnings("PointlessBitwiseExpression")
     public void writeLong(long i) throws IOException {
         // @formatter:off
-        either.get().writeBinary((byte) ((i >> 0)  & 0xFF));
-        either.get().writeBinary((byte) ((i >> 8)  & 0xFF));
-        either.get().writeBinary((byte) ((i >> 16) & 0xFF));
-        either.get().writeBinary((byte) ((i >> 24) & 0xFF));
-        either.get().writeBinary((byte) ((i >> 32) & 0xFF));
-        either.get().writeBinary((byte) ((i >> 40) & 0xFF));
-        either.get().writeBinary((byte) ((i >> 48) & 0xFF));
-        either.get().writeBinary((byte) ((i >> 56) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 0)  & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 8)  & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 16) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 24) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 32) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 40) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 48) & 0xFF));
+        switcher.get().writeBinary((byte) ((i >> 56) & 0xFF));
         // @formatter:on
     }
 
@@ -105,22 +105,23 @@ public class BinarySerializer {
 
     public void writeBytesBinary(byte[] bs) throws IOException {
         writeVarInt(bs.length);
-        either.get().writeBinary(bs);
+        switcher.get().writeBinary(bs);
     }
 
     public void flushToTarget(boolean force) throws IOException {
-        either.get().flushToTarget(force);
+        switcher.get().flushToTarget(force);
     }
 
     public void maybeEnableCompressed() {
-        if (enableCompress)
-            either.select(true);
+        if (enableCompress) {
+            switcher.select(false);
+        }
     }
 
     public void maybeDisableCompressed() throws IOException {
         if (enableCompress) {
-            either.get().flushToTarget(true);
-            either.select(false);
+            switcher.get().flushToTarget(true);
+            switcher.select(true);
         }
     }
 
@@ -133,18 +134,18 @@ public class BinarySerializer {
     public void writeDouble(double datum) throws IOException {
         long x = Double.doubleToLongBits(datum);
         // @formatter:off
-        either.get().writeBinary((byte) ((x >>> 0)  & 0xFF));
-        either.get().writeBinary((byte) ((x >>> 8)  & 0xFF));
-        either.get().writeBinary((byte) ((x >>> 16) & 0xFF));
-        either.get().writeBinary((byte) ((x >>> 24) & 0xFF));
-        either.get().writeBinary((byte) ((x >>> 32) & 0xFF));
-        either.get().writeBinary((byte) ((x >>> 40) & 0xFF));
-        either.get().writeBinary((byte) ((x >>> 48) & 0xFF));
-        either.get().writeBinary((byte) ((x >>> 56) & 0xFF));
+        switcher.get().writeBinary((byte) ((x >>> 0)  & 0xFF));
+        switcher.get().writeBinary((byte) ((x >>> 8)  & 0xFF));
+        switcher.get().writeBinary((byte) ((x >>> 16) & 0xFF));
+        switcher.get().writeBinary((byte) ((x >>> 24) & 0xFF));
+        switcher.get().writeBinary((byte) ((x >>> 32) & 0xFF));
+        switcher.get().writeBinary((byte) ((x >>> 40) & 0xFF));
+        switcher.get().writeBinary((byte) ((x >>> 48) & 0xFF));
+        switcher.get().writeBinary((byte) ((x >>> 56) & 0xFF));
         // @formatter:on
     }
 
     public void writeBytes(byte[] bytes) throws IOException {
-        either.get().writeBinary(bytes);
+        switcher.get().writeBinary(bytes);
     }
 }


Test patch:
diff --git a/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/misc/EitherTest.java b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/misc/EitherTest.java
new file mode 100644
index 0000000..7781326
--- /dev/null
+++ b/clickhouse-native-jdbc/src/test/java/com/github/housepower/jdbc/misc/EitherTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.misc;
+
+import com.github.housepower.jdbc.exception.InvalidOperationException;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class EitherTest {
+
+    @Test
+    public void testLeft() {
+        Either<Integer, String> left = Either.left(1);
+        assertFalse(left.isRight());
+        assertEquals(1, left.getLeft());
+        assertThrows(InvalidOperationException.class, left::getRight);
+        Either<Integer, String> mappedLeft = left.map(str -> str + "haha");
+        assertFalse(mappedLeft.isRight());
+        assertEquals(1, mappedLeft.getLeft());
+        Either<Integer, String> flatMappedLeft = left.flatMap(str -> Either.right(str + "haha"));
+        assertFalse(flatMappedLeft.isRight());
+        assertEquals(1, flatMappedLeft.getLeft());
+    }
+
+    @Test
+    public void testRight() {
+        Either<Integer, String> right = Either.right("haha");
+        assertTrue(right.isRight());
+        assertThrows(InvalidOperationException.class, right::getLeft);
+        assertEquals("haha", right.getRight());
+        Either<Integer, String> mappedRight = right.map(str -> str + "haha");
+        assertTrue(mappedRight.isRight());
+        assertEquals("hahahaha", mappedRight.getRight());
+        Either<Integer, String> flatMappedRight = right.flatMap(str -> Either.right(str + "haha"));
+        assertTrue(flatMappedRight.isRight());
+        assertEquals("hahahaha", flatMappedRight.getRight());
+        Either<Integer, String> flatMappedLeft = right.flatMap(str -> Either.left(1));
+        assertFalse(flatMappedLeft.isRight());
+        assertEquals(1, flatMappedLeft.getLeft());
+    }
+}