Repository: apache/shardingsphere
Issue: Wring rewritten SQL in mulitiple threads

## Bug Report

**For English only**, other languages will not accept.

Before report a bug, make sure you have:

- Searched open and closed [GitHub issues](https://github.com/apache/incubator-shardingsphere/issues).
- Read documentation: [ShardingSphere Doc](https://shardingsphere.apache.org/document/current/en/overview).

Please pay attention on issues you submitted, because we maybe need more details. 
If no response **more than 7 days** and we cannot reproduce it on current information, we will **close it**.

Please answer these questions before submitting your issue. Thanks!

### Which version of ShardingSphere did you use?

### Which project did you use? Sharding-JDBC or Sharding-Proxy?

### Expected behavior

### Actual behavior

### Reason analyze (If you can)

### Steps to reproduce the behavior, such as: SQL to execute, sharding rule configuration, when exception occur etc.

### Example codes for reproduce this issue (such as a github link).


Changed files:
sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/UpdateEncryptColumnTokenGenerator.java
sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectEncryptItemTokenGenerator.java
sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/WhereEncryptColumnTokenGenerator.java

diff --git a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectEncryptItemTokenGenerator.java b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectEncryptItemTokenGenerator.java
index 24e42660d43..174edb4ddf9 100644
--- a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectEncryptItemTokenGenerator.java
+++ b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectEncryptItemTokenGenerator.java
@@ -38,20 +38,13 @@ import java.util.LinkedList;
  */
 public final class SelectEncryptItemTokenGenerator implements CollectionSQLTokenGenerator<EncryptRule> {
     
-    private EncryptRule encryptRule;
-    
-    private OptimizedStatement optimizedStatement;
-    
-    private boolean isQueryWithCipherColumn;
-    
     @Override
     public Collection<SelectEncryptItemToken> generateSQLTokens(final OptimizedStatement optimizedStatement,
                                                                 final ParameterBuilder parameterBuilder, final EncryptRule rule, final boolean isQueryWithCipherColumn) {
         if (!isNeedToGenerateSQLToken(optimizedStatement)) {
             return Collections.emptyList();
         }
-        initParameters(rule, optimizedStatement, isQueryWithCipherColumn);
-        return createSelectCipherItemTokens();
+        return createSelectCipherItemTokens(rule, optimizedStatement, isQueryWithCipherColumn);
     }
     
     private boolean isNeedToGenerateSQLToken(final OptimizedStatement optimizedStatement) {
@@ -66,20 +59,14 @@ public final class SelectEncryptItemTokenGenerator implements CollectionSQLToken
         return optimizedStatement.getSQLStatement() instanceof SelectStatement && !optimizedStatement.getTables().isEmpty();
     }
     
-    private void initParameters(final EncryptRule rule, final OptimizedStatement optimizedStatement, final boolean isQueryWithCipherColumn) {
-        encryptRule = rule;
-        this.optimizedStatement = optimizedStatement;
-        this.isQueryWithCipherColumn = isQueryWithCipherColumn;
-    }
-    
-    private Collection<SelectEncryptItemToken> createSelectCipherItemTokens() {
+    private Collection<SelectEncryptItemToken> createSelectCipherItemTokens(final EncryptRule encryptRule, final OptimizedStatement optimizedStatement, final boolean isQueryWithCipherColumn) {
         Collection<SelectEncryptItemToken> result = new LinkedList<>();
         SelectItemsSegment selectItemsSegment = optimizedStatement.getSQLStatement().findSQLSegment(SelectItemsSegment.class).get();
         String tableName = optimizedStatement.getTables().getSingleTableName();
         Collection<String> logicColumns = encryptRule.getLogicColumns(tableName);
         for (SelectItemSegment each : selectItemsSegment.getSelectItems()) {
             if (isLogicColumn(each, logicColumns)) {
-                result.add(createSelectCipherItemToken(each, tableName));
+                result.add(createSelectCipherItemToken(each, tableName, encryptRule, isQueryWithCipherColumn));
             }
         }
         return result;
@@ -89,7 +76,7 @@ public final class SelectEncryptItemTokenGenerator implements CollectionSQLToken
         return each instanceof ColumnSelectItemSegment && logicColumns.contains(((ColumnSelectItemSegment) each).getName());
     }
     
-    private SelectEncryptItemToken createSelectCipherItemToken(final SelectItemSegment each, final String tableName) {
+    private SelectEncryptItemToken createSelectCipherItemToken(final SelectItemSegment each, final String tableName, final EncryptRule encryptRule, final boolean isQueryWithCipherColumn) {
         String columnName = ((ColumnSelectItemSegment) each).getName();
         Optional<String> plainColumn = encryptRule.getPlainColumn(tableName, columnName);
         if (!isQueryWithCipherColumn && plainColumn.isPresent()) {
diff --git a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/UpdateEncryptColumnTokenGenerator.java b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/UpdateEncryptColumnTokenGenerator.java
index 56844b8f9ea..7799091aaa3 100644
--- a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/UpdateEncryptColumnTokenGenerator.java
+++ b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/UpdateEncryptColumnTokenGenerator.java
@@ -41,54 +41,48 @@ import java.util.LinkedList;
  */
 public final class UpdateEncryptColumnTokenGenerator implements CollectionSQLTokenGenerator<EncryptRule> {
     
-    private EncryptRule encryptRule;
-    
-    private ParameterBuilder parameterBuilder;
-    
     @Override
     public Collection<EncryptColumnToken> generateSQLTokens(
             final OptimizedStatement optimizedStatement, final ParameterBuilder parameterBuilder, final EncryptRule encryptRule, final boolean isQueryWithCipherColumn) {
-        initParameter(parameterBuilder, encryptRule);
-        return optimizedStatement.getSQLStatement() instanceof UpdateStatement ? createUpdateEncryptColumnTokens(optimizedStatement) : Collections.<EncryptColumnToken>emptyList();
-    }
-    
-    private void initParameter(final ParameterBuilder parameterBuilder, final EncryptRule encryptRule) {
-        this.parameterBuilder = parameterBuilder;
-        this.encryptRule = encryptRule;
+        return optimizedStatement.getSQLStatement() instanceof UpdateStatement 
+                ? createUpdateEncryptColumnTokens(parameterBuilder, encryptRule, optimizedStatement) : Collections.<EncryptColumnToken>emptyList();
     }
     
-    private Collection<EncryptColumnToken> createUpdateEncryptColumnTokens(final OptimizedStatement optimizedStatement) {
+    private Collection<EncryptColumnToken> createUpdateEncryptColumnTokens(final ParameterBuilder parameterBuilder, final EncryptRule encryptRule, final OptimizedStatement optimizedStatement) {
         Collection<EncryptColumnToken> result = new LinkedList<>();
         String tableName = optimizedStatement.getTables().getSingleTableName();
         for (AssignmentSegment each : ((UpdateStatement) optimizedStatement.getSQLStatement()).getSetAssignment().getAssignments()) {
             if (encryptRule.getShardingEncryptor(tableName, each.getColumn().getName()).isPresent()) {
-                result.add(createUpdateEncryptColumnToken(tableName, each));
+                result.add(createUpdateEncryptColumnToken(parameterBuilder, encryptRule, tableName, each));
             }
         }
         return result;
     }
     
-    private EncryptColumnToken createUpdateEncryptColumnToken(final String tableName, final AssignmentSegment assignmentSegment) {
+    private EncryptColumnToken createUpdateEncryptColumnToken(final ParameterBuilder parameterBuilder, 
+                                                              final EncryptRule encryptRule, final String tableName, final AssignmentSegment assignmentSegment) {
         return assignmentSegment.getValue() instanceof ParameterMarkerExpressionSegment 
-                ? createUpdateEncryptParameterColumnToken(tableName, assignmentSegment) : createUpdateEncryptLiteralColumnToken(tableName, assignmentSegment);
+                ? createUpdateEncryptParameterColumnToken(parameterBuilder, encryptRule, tableName, assignmentSegment) 
+                : createUpdateEncryptLiteralColumnToken(encryptRule, tableName, assignmentSegment);
     }
     
-    private EncryptColumnToken createUpdateEncryptParameterColumnToken(final String tableName, final AssignmentSegment assignmentSegment) {
+    private EncryptColumnToken createUpdateEncryptParameterColumnToken(final ParameterBuilder parameterBuilder, 
+                                                                       final EncryptRule encryptRule, final String tableName, final AssignmentSegment assignmentSegment) {
         UpdateEncryptParameterColumnToken result = new UpdateEncryptParameterColumnToken(assignmentSegment.getColumn().getStartIndex(), assignmentSegment.getStopIndex());
         Optional<String> plainColumn = encryptRule.getPlainColumn(tableName, assignmentSegment.getColumn().getName());
         if (plainColumn.isPresent()) {
             result.addUpdateColumn(plainColumn.get());
             result.addUpdateColumn(encryptRule.getCipherColumn(tableName, assignmentSegment.getColumn().getName()));
-            addCipherColumnValueToParameterBuilder(tableName, assignmentSegment);
+            addCipherColumnValueToParameterBuilder(parameterBuilder, encryptRule, tableName, assignmentSegment);
         } else {
             result.addUpdateColumn(encryptRule.getCipherColumn(tableName, assignmentSegment.getColumn().getName()));
-            setCipherColumnValueToParameterBuilder(tableName, assignmentSegment);
+            setCipherColumnValueToParameterBuilder(parameterBuilder, encryptRule, tableName, assignmentSegment);
         }
-        addAssistedQueryUpdateColumn(tableName, assignmentSegment, result);
+        addAssistedQueryUpdateColumn(parameterBuilder, encryptRule, tableName, assignmentSegment, result);
         return result;
     }
     
-    private void addCipherColumnValueToParameterBuilder(final String tableName, final AssignmentSegment assignmentSegment) {
+    private void addCipherColumnValueToParameterBuilder(final ParameterBuilder parameterBuilder, final EncryptRule encryptRule, final String tableName, final AssignmentSegment assignmentSegment) {
         int logicColumnValueIndex = ((ParameterMarkerExpressionSegment) assignmentSegment.getValue()).getParameterMarkerIndex();
         Object originalColumnValue = parameterBuilder.getOriginalParameters().get(logicColumnValueIndex);
         Object cipherColumnValue = encryptRule.getEncryptColumnValues(
@@ -96,7 +90,7 @@ public final class UpdateEncryptColumnTokenGenerator implements CollectionSQLTok
         ((BaseParameterBuilder) parameterBuilder).getAddedIndexAndParameters().put(logicColumnValueIndex + 1, cipherColumnValue);
     }
     
-    private void setCipherColumnValueToParameterBuilder(final String tableName, final AssignmentSegment assignmentSegment) {
+    private void setCipherColumnValueToParameterBuilder(final ParameterBuilder parameterBuilder, final EncryptRule encryptRule, final String tableName, final AssignmentSegment assignmentSegment) {
         int logicColumnValueIndex = ((ParameterMarkerExpressionSegment) assignmentSegment.getValue()).getParameterMarkerIndex();
         Object originalColumnValue = parameterBuilder.getOriginalParameters().get(logicColumnValueIndex);
         Object cipherColumnValue = encryptRule.getEncryptColumnValues(
@@ -104,15 +98,17 @@ public final class UpdateEncryptColumnTokenGenerator implements CollectionSQLTok
         ((BaseParameterBuilder) parameterBuilder).getReplacedIndexAndParameters().put(logicColumnValueIndex, cipherColumnValue);
     }
     
-    private void addAssistedQueryUpdateColumn(final String tableName, final AssignmentSegment assignmentSegment, final UpdateEncryptParameterColumnToken result) {
+    private void addAssistedQueryUpdateColumn(final ParameterBuilder parameterBuilder, final EncryptRule encryptRule,
+                                              final String tableName, final AssignmentSegment assignmentSegment, final UpdateEncryptParameterColumnToken result) {
         Optional<String> assistedQueryColumn = encryptRule.getAssistedQueryColumn(tableName, assignmentSegment.getColumn().getName());
         if (assistedQueryColumn.isPresent()) {
             result.addUpdateColumn(assistedQueryColumn.get());
-            addAssistedQueryColumnValueToParameterBuilder(tableName, assignmentSegment);
+            addAssistedQueryColumnValueToParameterBuilder(parameterBuilder, encryptRule, tableName, assignmentSegment);
         }
     }
     
-    private void addAssistedQueryColumnValueToParameterBuilder(final String tableName, final AssignmentSegment assignmentSegment) {
+    private void addAssistedQueryColumnValueToParameterBuilder(final ParameterBuilder parameterBuilder, 
+                                                               final EncryptRule encryptRule, final String tableName, final AssignmentSegment assignmentSegment) {
         int logicColumnValueIndex = ((ParameterMarkerExpressionSegment) assignmentSegment.getValue()).getParameterMarkerIndex();
         Object originalColumnValue = parameterBuilder.getOriginalParameters().get(logicColumnValueIndex);
         Object assistedQueryColumnValue = encryptRule.getEncryptAssistedColumnValues(
@@ -120,15 +116,15 @@ public final class UpdateEncryptColumnTokenGenerator implements CollectionSQLTok
         ((BaseParameterBuilder) parameterBuilder).getAddedIndexAndParameters().put(logicColumnValueIndex + 2, assistedQueryColumnValue);
     }
     
-    private EncryptColumnToken createUpdateEncryptLiteralColumnToken(final String tableName, final AssignmentSegment assignmentSegment) {
+    private EncryptColumnToken createUpdateEncryptLiteralColumnToken(final EncryptRule encryptRule, final String tableName, final AssignmentSegment assignmentSegment) {
         UpdateEncryptLiteralColumnToken result = new UpdateEncryptLiteralColumnToken(assignmentSegment.getColumn().getStartIndex(), assignmentSegment.getStopIndex());
-        addPlainUpdateColumn(tableName, assignmentSegment, result);
-        addCipherUpdateColumn(tableName, assignmentSegment, result);
-        addAssistedQueryUpdateColumn(tableName, assignmentSegment, result);
+        addPlainUpdateColumn(encryptRule, tableName, assignmentSegment, result);
+        addCipherUpdateColumn(encryptRule, tableName, assignmentSegment, result);
+        addAssistedQueryUpdateColumn(encryptRule, tableName, assignmentSegment, result);
         return result;
     }
     
-    private void addPlainUpdateColumn(final String tableName, final AssignmentSegment assignmentSegment, final UpdateEncryptLiteralColumnToken result) {
+    private void addPlainUpdateColumn(final EncryptRule encryptRule, final String tableName, final AssignmentSegment assignmentSegment, final UpdateEncryptLiteralColumnToken result) {
         Object originalColumnValue = ((LiteralExpressionSegment) assignmentSegment.getValue()).getLiterals();
         Optional<String> plainColumn = encryptRule.getPlainColumn(tableName, assignmentSegment.getColumn().getName());
         if (plainColumn.isPresent()) {
@@ -136,14 +132,14 @@ public final class UpdateEncryptColumnTokenGenerator implements CollectionSQLTok
         }
     }
     
-    private void addCipherUpdateColumn(final String tableName, final AssignmentSegment assignmentSegment, final UpdateEncryptLiteralColumnToken result) {
+    private void addCipherUpdateColumn(final EncryptRule encryptRule, final String tableName, final AssignmentSegment assignmentSegment, final UpdateEncryptLiteralColumnToken result) {
         Object originalColumnValue = ((LiteralExpressionSegment) assignmentSegment.getValue()).getLiterals();
         Object cipherColumnValue = encryptRule.getEncryptColumnValues(
                 tableName, assignmentSegment.getColumn().getName(), Collections.singletonList(originalColumnValue)).iterator().next();
         result.addUpdateColumn(encryptRule.getCipherColumn(tableName, assignmentSegment.getColumn().getName()), cipherColumnValue);
     }
     
-    private void addAssistedQueryUpdateColumn(final String tableName, final AssignmentSegment assignmentSegment, final UpdateEncryptLiteralColumnToken result) {
+    private void addAssistedQueryUpdateColumn(final EncryptRule encryptRule, final String tableName, final AssignmentSegment assignmentSegment, final UpdateEncryptLiteralColumnToken result) {
         Object originalColumnValue = ((LiteralExpressionSegment) assignmentSegment.getValue()).getLiterals();
         Optional<String> assistedQueryColumn = encryptRule.getAssistedQueryColumn(tableName, assignmentSegment.getColumn().getName());
         if (assistedQueryColumn.isPresent()) {
diff --git a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/WhereEncryptColumnTokenGenerator.java b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/WhereEncryptColumnTokenGenerator.java
index 42ccc261adc..ca88827e730 100644
--- a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/WhereEncryptColumnTokenGenerator.java
+++ b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/WhereEncryptColumnTokenGenerator.java
@@ -42,58 +42,49 @@ import java.util.Map.Entry;
  */
 public final class WhereEncryptColumnTokenGenerator implements CollectionSQLTokenGenerator<EncryptRule> {
     
-    private EncryptRule encryptRule;
-    
-    private ParameterBuilder parameterBuilder;
-    
-    private boolean isQueryWithCipherColumn;
-    
     @Override
     public Collection<EncryptColumnToken> generateSQLTokens(
             final OptimizedStatement optimizedStatement, final ParameterBuilder parameterBuilder, final EncryptRule encryptRule, final boolean isQueryWithCipherColumn) {
-        initParameters(parameterBuilder, encryptRule, isQueryWithCipherColumn);
         return optimizedStatement instanceof ConditionOptimizedStatement
-                ? createWhereEncryptColumnTokens((ConditionOptimizedStatement) optimizedStatement) : Collections.<EncryptColumnToken>emptyList();
-    }
-    
-    private void initParameters(final ParameterBuilder parameterBuilder, final EncryptRule encryptRule, final boolean isQueryWithCipherColumn) {
-        this.parameterBuilder = parameterBuilder;
-        this.encryptRule = encryptRule;
-        this.isQueryWithCipherColumn = isQueryWithCipherColumn;
+                ? createWhereEncryptColumnTokens(parameterBuilder, encryptRule, isQueryWithCipherColumn, (ConditionOptimizedStatement) optimizedStatement) 
+                : Collections.<EncryptColumnToken>emptyList();
     }
     
-    private Collection<EncryptColumnToken> createWhereEncryptColumnTokens(final ConditionOptimizedStatement optimizedStatement) {
+    private Collection<EncryptColumnToken> createWhereEncryptColumnTokens(final ParameterBuilder parameterBuilder, 
+                                                                          final EncryptRule encryptRule, final boolean isQueryWithCipherColumn, final ConditionOptimizedStatement optimizedStatement) {
         Collection<EncryptColumnToken> result = new LinkedList<>();
         for (EncryptCondition each : optimizedStatement.getEncryptConditions().getConditions()) {
-            result.add(createWhereEncryptColumnToken(each));
+            result.add(createWhereEncryptColumnToken(parameterBuilder, encryptRule, isQueryWithCipherColumn, each));
         }
         return result;
     }
     
-    private WhereEncryptColumnToken createWhereEncryptColumnToken(final EncryptCondition encryptCondition) {
+    private WhereEncryptColumnToken createWhereEncryptColumnToken(final ParameterBuilder parameterBuilder, 
+                                                                  final EncryptRule encryptRule, final boolean isQueryWithCipherColumn, final EncryptCondition encryptCondition) {
         List<Object> originalColumnValues = encryptCondition.getValues(parameterBuilder.getOriginalParameters());
         if (isQueryWithCipherColumn) {
-            return createWhereEncryptColumnToken(encryptCondition, originalColumnValues);
+            return createWhereEncryptColumnToken(parameterBuilder, encryptRule, encryptCondition, originalColumnValues);
         }
-        return new WhereEncryptColumnToken(encryptCondition.getStartIndex(), encryptCondition.getStopIndex(), getPlainColumn(encryptCondition, encryptRule),
+        return new WhereEncryptColumnToken(encryptCondition.getStartIndex(), encryptCondition.getStopIndex(), getPlainColumn(encryptRule, encryptCondition),
                 getPositionValues(encryptCondition.getPositionValueMap().keySet(), originalColumnValues), encryptCondition.getPositionIndexMap().keySet(), encryptCondition.getOperator());
     }
     
-    private WhereEncryptColumnToken createWhereEncryptColumnToken(final EncryptCondition encryptCondition, final List<Object> originalValues) {
-        String encryptedColumnName = getEncryptedColumnName(encryptCondition);
-        List<Object> encryptedColumnValues = getEncryptedColumnValues(encryptCondition, originalValues);
+    private WhereEncryptColumnToken createWhereEncryptColumnToken(final ParameterBuilder parameterBuilder, 
+                                                                  final EncryptRule encryptRule, final EncryptCondition encryptCondition, final List<Object> originalValues) {
+        String encryptedColumnName = getEncryptedColumnName(encryptRule, encryptCondition);
+        List<Object> encryptedColumnValues = getEncryptedColumnValues(encryptRule, encryptCondition, originalValues);
         encryptParameters(encryptCondition.getPositionIndexMap(), encryptedColumnValues, parameterBuilder);
         return new WhereEncryptColumnToken(encryptCondition.getStartIndex(), encryptCondition.getStopIndex(), encryptedColumnName,
                 getPositionValues(encryptCondition.getPositionValueMap().keySet(), encryptedColumnValues), encryptCondition.getPositionIndexMap().keySet(), encryptCondition.getOperator());
     }
     
-    private String getEncryptedColumnName(final EncryptCondition encryptCondition) {
+    private String getEncryptedColumnName(final EncryptRule encryptRule, final EncryptCondition encryptCondition) {
         Optional<String> assistedQueryColumn = encryptRule.getAssistedQueryColumn(encryptCondition.getTableName(), encryptCondition.getColumnName());
         return assistedQueryColumn.isPresent() 
                 ? assistedQueryColumn.get() : encryptRule.getCipherColumn(encryptCondition.getTableName(), encryptCondition.getColumnName());
     }
     
-    private List<Object> getEncryptedColumnValues(final EncryptCondition encryptCondition, final List<Object> originalValues) {
+    private List<Object> getEncryptedColumnValues(final EncryptRule encryptRule, final EncryptCondition encryptCondition, final List<Object> originalValues) {
         Optional<String> assistedQueryColumn = encryptRule.getAssistedQueryColumn(encryptCondition.getTableName(), encryptCondition.getColumnName());
         return assistedQueryColumn.isPresent() 
                 ? encryptRule.getEncryptAssistedColumnValues(encryptCondition.getTableName(), encryptCondition.getColumnName(), originalValues) 
@@ -116,7 +107,7 @@ public final class WhereEncryptColumnTokenGenerator implements CollectionSQLToke
         return result;
     }
     
-    private String getPlainColumn(final EncryptCondition encryptCondition, final EncryptRule encryptRule) {
+    private String getPlainColumn(final EncryptRule encryptRule, final EncryptCondition encryptCondition) {
         Optional<String> result = encryptRule.getPlainColumn(encryptCondition.getTableName(), encryptCondition.getColumnName());
         if (result.isPresent()) {
             return result.get();