Repository: apache/shardingsphere
Issue: Column types disordered when use prepared statement in Proxy

Please answer these questions before submitting your issue. Thanks!
开源不易，我们希望将精力放在完成新功能和解决有价值的问题上，为了让大家的配合更具有效率，请填写以下列出的全部问题

### Which version of Sharding-Sphere do you using?（您使用的Sharding-Sphere版本为？）
dev

### Expected behavior （您预期的结果是）
correct prepared statement result

### Actual behavior （实际运行的结果是）
a chance to triger wrong result

### Steps to reproduce the behavior （可重现问题的操作步骤）
use prepared statement in Proxy

### Please provide the reproduce example codes (such as github link)，otherwise we will label the issue as Invalid and close it.（为了节省复现问题的时间，请务必提供可重现的代码，否则我们会将issue直接标记为invalid并关闭）
example

Code should based on https://github.com/sharding-sphere/sharding-sphere-example
（代码请基于 https://github.com/sharding-sphere/sharding-sphere-example）


Changed files:
sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/JDBCExecuteWorker.java
sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementExecuteWorker.java
sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementBackendHandler.java

diff --git a/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/JDBCExecuteWorker.java b/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/JDBCExecuteWorker.java
index 90358c3135f..b6bb34dd4e4 100644
--- a/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/JDBCExecuteWorker.java
+++ b/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/JDBCExecuteWorker.java
@@ -35,6 +35,8 @@ import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.Callable;
 
 /**
@@ -86,16 +88,18 @@ public abstract class JDBCExecuteWorker implements Callable<CommandResponsePacke
             return new CommandResponsePackets(new OKPacket(++currentSequenceId));
         }
         CommandResponsePackets result = new CommandResponsePackets(new FieldCountPacket(++currentSequenceId, columnCount));
+        List<ColumnType> columnTypes = new ArrayList<>(128);
         for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
-            setColumnType(ColumnType.valueOfJDBCType(resultSetMetaData.getColumnType(columnIndex)));
+            columnTypes.add(ColumnType.valueOfJDBCType(resultSetMetaData.getColumnType(columnIndex)));
             result.addPacket(new ColumnDefinition41Packet(++currentSequenceId, resultSetMetaData, columnIndex));
         }
+        setColumnTypes(columnTypes);
         result.addPacket(new EofPacket(++currentSequenceId));
         return result;
     }
     
     // TODO why only prepareStatement need this?
-    protected void setColumnType(final ColumnType columnType) {
+    protected void setColumnTypes(final List<ColumnType> columnTypes) {
     }
     
     private long getGeneratedKey() throws SQLException {
diff --git a/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementBackendHandler.java b/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementBackendHandler.java
index 68508d04c6c..3bcba985556 100644
--- a/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementBackendHandler.java
+++ b/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementBackendHandler.java
@@ -28,7 +28,7 @@ import io.shardingsphere.proxy.transport.mysql.packet.command.CommandResponsePac
 import io.shardingsphere.proxy.transport.mysql.packet.command.statement.PreparedStatementRegistry;
 import io.shardingsphere.proxy.transport.mysql.packet.command.statement.execute.BinaryResultSetRowPacket;
 import io.shardingsphere.proxy.transport.mysql.packet.command.statement.execute.PreparedStatementParameter;
-import lombok.Getter;
+import lombok.Setter;
 
 import java.sql.Connection;
 import java.sql.PreparedStatement;
@@ -37,7 +37,6 @@ import java.sql.Statement;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.Callable;
-import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * Statement protocol backend handler via JDBC to connect databases.
@@ -51,8 +50,8 @@ public final class JDBCStatementBackendHandler extends JDBCBackendHandler {
     
     private final DatabaseType databaseType;
     
-    @Getter
-    private final List<ColumnType> columnTypes;
+    @Setter
+    private List<ColumnType> columnTypes;
     
     private final RuleRegistry ruleRegistry;
     
@@ -60,7 +59,6 @@ public final class JDBCStatementBackendHandler extends JDBCBackendHandler {
         super(PreparedStatementRegistry.getInstance().getSQL(statementId));
         this.preparedStatementParameters = preparedStatementParameters;
         this.databaseType = databaseType;
-        columnTypes = new CopyOnWriteArrayList<>();
         ruleRegistry = RuleRegistry.getInstance();
     }
     
diff --git a/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementExecuteWorker.java b/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementExecuteWorker.java
index 9f2e212ebc0..3f7758e5082 100644
--- a/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementExecuteWorker.java
+++ b/sharding-proxy/src/main/java/io/shardingsphere/proxy/backend/common/jdbc/statement/JDBCStatementExecuteWorker.java
@@ -22,6 +22,7 @@ import io.shardingsphere.proxy.transport.mysql.constant.ColumnType;
 
 import java.sql.PreparedStatement;
 import java.sql.SQLException;
+import java.util.List;
 
 /**
  * Statement execute worker.
@@ -45,7 +46,7 @@ public final class JDBCStatementExecuteWorker extends JDBCExecuteWorker {
     }
     
     @Override
-    protected void setColumnType(final ColumnType columnType) {
-        ((JDBCStatementBackendHandler) getJdbcBackendHandler()).getColumnTypes().add(columnType);
+    protected void setColumnTypes(final List<ColumnType> columnTypes) {
+        ((JDBCStatementBackendHandler) getJdbcBackendHandler()).setColumnTypes(columnTypes);
     }
 }