Repository: apache/shardingsphere
Issue: Can not rewrite correctly when use plainColumn

## 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?
4.0.0.RC2
### Which project did you use? Sharding-JDBC or Sharding-Proxy?
Sharding-JDBC
### Expected behavior
When use plainColumn, The SQL will be rewritten to Select plainColumn from tb.
### Actual behavior
When use plainColumn, The SQL will be rewritten to Select cipherColumn from tb.
### 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/EncryptTokenGenerateEngine.java
sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetTest.java
sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSet.java
sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/rule/EncryptRule.java
sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/pojo/SelectCipherItemToken.java
sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatementTest.java
sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatement.java
sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSetMetaData.java
sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/strategy/encrypt/EncryptTable.java
sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/common/base/AbstractEncryptJDBCDatabaseAndTableTest.java
sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetMetaData.java
sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/adapter/AbstractResultSetAdapter.java
sharding-core/sharding-core-rewrite/src/test/java/org/apache/shardingsphere/core/rewrite/rewriter/ShardingSQLRewriteEngineTest.java
sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptPreparedStatement.java
sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectCipherItemTokenGenerator.java

diff --git a/sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/rule/EncryptRule.java b/sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/rule/EncryptRule.java
index f0d7cd4b10a..6944d756e57 100644
--- a/sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/rule/EncryptRule.java
+++ b/sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/rule/EncryptRule.java
@@ -266,6 +266,19 @@ public final class EncryptRule implements BaseRule {
         return tables.get(logicTable).getLogicAndCipherColumns();
     }
     
+    /**
+     * Get logic and plain columns.
+     *
+     * @param logicTable logic table 
+     * @return logic and plain columns
+     */
+    public Map<String, String> getLogicAndPlainColumns(final String logicTable) {
+        if (!tables.containsKey(logicTable)) {
+            return Collections.emptyMap();
+        }
+        return tables.get(logicTable).getLogicAndPlainColumns();
+    }
+    
     /**
      * Get encrypt assisted column values.
      *
diff --git a/sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/strategy/encrypt/EncryptTable.java b/sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/strategy/encrypt/EncryptTable.java
index afc4f4e61bf..a68973c4de5 100644
--- a/sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/strategy/encrypt/EncryptTable.java
+++ b/sharding-core/sharding-core-common/src/main/java/org/apache/shardingsphere/core/strategy/encrypt/EncryptTable.java
@@ -198,4 +198,22 @@ public final class EncryptTable {
             }
         });
     }
+    
+    /**
+     * Get logic and plain columns.
+     *
+     * @return logic and plain columns
+     */
+    public Map<String, String> getLogicAndPlainColumns() {
+        return Maps.transformValues(columns, new Function<EncryptColumn, String>() {
+            
+            @Override
+            public String apply(final EncryptColumn input) {
+                if (input.getPlainColumn().isPresent()) {
+                    return input.getPlainColumn().get();
+                }
+                throw new ShardingException("Plain column is null.");
+            }
+        });
+    }
 }
diff --git a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/EncryptTokenGenerateEngine.java b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/EncryptTokenGenerateEngine.java
index 447debc09c8..decd14ba02d 100644
--- a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/EncryptTokenGenerateEngine.java
+++ b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/EncryptTokenGenerateEngine.java
@@ -23,7 +23,7 @@ import org.apache.shardingsphere.core.rewrite.token.generator.InsertSetCipherCol
 import org.apache.shardingsphere.core.rewrite.token.generator.InsertSetQueryAndPlainColumnsTokenGenerator;
 import org.apache.shardingsphere.core.rewrite.token.generator.InsertValuesTokenGenerator;
 import org.apache.shardingsphere.core.rewrite.token.generator.SQLTokenGenerator;
-import org.apache.shardingsphere.core.rewrite.token.generator.SelectCipherItemTokenGenerator;
+import org.apache.shardingsphere.core.rewrite.token.generator.SelectEncryptItemTokenGenerator;
 import org.apache.shardingsphere.core.rewrite.token.generator.UpdateEncryptColumnTokenGenerator;
 import org.apache.shardingsphere.core.rewrite.token.generator.WhereEncryptColumnTokenGenerator;
 import org.apache.shardingsphere.core.rule.EncryptRule;
@@ -41,7 +41,7 @@ public final class EncryptTokenGenerateEngine extends SQLTokenGenerateEngine<Enc
     private static final Collection<SQLTokenGenerator> SQL_TOKEN_GENERATORS = new LinkedList<>();
     
     static {
-        SQL_TOKEN_GENERATORS.add(new SelectCipherItemTokenGenerator());
+        SQL_TOKEN_GENERATORS.add(new SelectEncryptItemTokenGenerator());
         SQL_TOKEN_GENERATORS.add(new UpdateEncryptColumnTokenGenerator());
         SQL_TOKEN_GENERATORS.add(new WhereEncryptColumnTokenGenerator());
         SQL_TOKEN_GENERATORS.add(new InsertCipherNameTokenGenerator());
diff --git a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectCipherItemTokenGenerator.java b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectEncryptItemTokenGenerator.java
similarity index 70%
rename from sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectCipherItemTokenGenerator.java
rename to sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectEncryptItemTokenGenerator.java
index 45f1ff485ca..24e42660d43 100644
--- a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectCipherItemTokenGenerator.java
+++ b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/generator/SelectEncryptItemTokenGenerator.java
@@ -24,7 +24,7 @@ import org.apache.shardingsphere.core.parse.sql.segment.dml.item.SelectItemSegme
 import org.apache.shardingsphere.core.parse.sql.segment.dml.item.SelectItemsSegment;
 import org.apache.shardingsphere.core.parse.sql.statement.dml.SelectStatement;
 import org.apache.shardingsphere.core.rewrite.builder.ParameterBuilder;
-import org.apache.shardingsphere.core.rewrite.token.pojo.SelectCipherItemToken;
+import org.apache.shardingsphere.core.rewrite.token.pojo.SelectEncryptItemToken;
 import org.apache.shardingsphere.core.rule.EncryptRule;
 
 import java.util.Collection;
@@ -36,19 +36,21 @@ import java.util.LinkedList;
  *
  * @author panjuan
  */
-public final class SelectCipherItemTokenGenerator implements CollectionSQLTokenGenerator<EncryptRule> {
+public final class SelectEncryptItemTokenGenerator implements CollectionSQLTokenGenerator<EncryptRule> {
     
     private EncryptRule encryptRule;
     
     private OptimizedStatement optimizedStatement;
     
+    private boolean isQueryWithCipherColumn;
+    
     @Override
-    public Collection<SelectCipherItemToken> generateSQLTokens(final OptimizedStatement optimizedStatement, 
-                                                               final ParameterBuilder parameterBuilder, final EncryptRule rule, final boolean isQueryWithCipherColumn) {
+    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);
+        initParameters(rule, optimizedStatement, isQueryWithCipherColumn);
         return createSelectCipherItemTokens();
     }
     
@@ -64,13 +66,14 @@ public final class SelectCipherItemTokenGenerator implements CollectionSQLTokenG
         return optimizedStatement.getSQLStatement() instanceof SelectStatement && !optimizedStatement.getTables().isEmpty();
     }
     
-    private void initParameters(final EncryptRule rule, final OptimizedStatement optimizedStatement) {
+    private void initParameters(final EncryptRule rule, final OptimizedStatement optimizedStatement, final boolean isQueryWithCipherColumn) {
         encryptRule = rule;
         this.optimizedStatement = optimizedStatement;
+        this.isQueryWithCipherColumn = isQueryWithCipherColumn;
     }
     
-    private Collection<SelectCipherItemToken> createSelectCipherItemTokens() {
-        Collection<SelectCipherItemToken> result = new LinkedList<>();
+    private Collection<SelectEncryptItemToken> createSelectCipherItemTokens() {
+        Collection<SelectEncryptItemToken> result = new LinkedList<>();
         SelectItemsSegment selectItemsSegment = optimizedStatement.getSQLStatement().findSQLSegment(SelectItemsSegment.class).get();
         String tableName = optimizedStatement.getTables().getSingleTableName();
         Collection<String> logicColumns = encryptRule.getLogicColumns(tableName);
@@ -86,8 +89,12 @@ public final class SelectCipherItemTokenGenerator implements CollectionSQLTokenG
         return each instanceof ColumnSelectItemSegment && logicColumns.contains(((ColumnSelectItemSegment) each).getName());
     }
     
-    private SelectCipherItemToken createSelectCipherItemToken(final SelectItemSegment each, final String tableName) {
-        return new SelectCipherItemToken(each.getStartIndex(),
-                each.getStopIndex(), encryptRule.getCipherColumn(tableName, ((ColumnSelectItemSegment) each).getName()));
+    private SelectEncryptItemToken createSelectCipherItemToken(final SelectItemSegment each, final String tableName) {
+        String columnName = ((ColumnSelectItemSegment) each).getName();
+        Optional<String> plainColumn = encryptRule.getPlainColumn(tableName, columnName);
+        if (!isQueryWithCipherColumn && plainColumn.isPresent()) {
+            return new SelectEncryptItemToken(each.getStartIndex(), each.getStopIndex(), plainColumn.get());
+        }
+        return new SelectEncryptItemToken(each.getStartIndex(), each.getStopIndex(), encryptRule.getCipherColumn(tableName, columnName));
     }
 }
diff --git a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/pojo/SelectCipherItemToken.java b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/pojo/SelectEncryptItemToken.java
similarity index 86%
rename from sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/pojo/SelectCipherItemToken.java
rename to sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/pojo/SelectEncryptItemToken.java
index 8202e68b27f..89117ebc6fd 100644
--- a/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/pojo/SelectCipherItemToken.java
+++ b/sharding-core/sharding-core-rewrite/src/main/java/org/apache/shardingsphere/core/rewrite/token/pojo/SelectEncryptItemToken.java
@@ -25,13 +25,13 @@ import lombok.Getter;
  * @author panjuan
  */
 @Getter
-public final class SelectCipherItemToken extends SQLToken implements Substitutable {
+public final class SelectEncryptItemToken extends SQLToken implements Substitutable {
     
     private final int stopIndex;
     
     private final String selectItemName;
     
-    public SelectCipherItemToken(final int startIndex, final int stopIndex, final String selectItemName) {
+    public SelectEncryptItemToken(final int startIndex, final int stopIndex, final String selectItemName) {
         super(startIndex);
         this.stopIndex = stopIndex;
         this.selectItemName = selectItemName;
diff --git a/sharding-core/sharding-core-rewrite/src/test/java/org/apache/shardingsphere/core/rewrite/rewriter/ShardingSQLRewriteEngineTest.java b/sharding-core/sharding-core-rewrite/src/test/java/org/apache/shardingsphere/core/rewrite/rewriter/ShardingSQLRewriteEngineTest.java
index aa33067941b..75fae0b4c9e 100644
--- a/sharding-core/sharding-core-rewrite/src/test/java/org/apache/shardingsphere/core/rewrite/rewriter/ShardingSQLRewriteEngineTest.java
+++ b/sharding-core/sharding-core-rewrite/src/test/java/org/apache/shardingsphere/core/rewrite/rewriter/ShardingSQLRewriteEngineTest.java
@@ -901,7 +901,7 @@ public final class ShardingSQLRewriteEngineTest {
     @Test
     public void assertRewriteSelectInWithShardingEncryptorWithPlain() {
         SQLRewriteEngine rewriteEngine = createSQLRewriteEngine(createSQLRouteResultForSelectInWithShardingEncryptor(), "SELECT id FROM table_z WHERE id in (3,5)", Collections.emptyList(), false);
-        assertThat(rewriteEngine.generateSQL(null, logicTableAndActualTables).getSql(), is("SELECT cipher FROM table_z WHERE plain IN ('3', '5')"));
+        assertThat(rewriteEngine.generateSQL(null, logicTableAndActualTables).getSql(), is("SELECT plain FROM table_z WHERE plain IN ('3', '5')"));
     }
     
     private SQLRouteResult createSQLRouteResultForSelectInWithShardingEncryptor() {
@@ -1030,7 +1030,7 @@ public final class ShardingSQLRewriteEngineTest {
     public void assertRewriteSelectEqualWithShardingEncryptorWithPlain() {
         SQLRewriteEngine rewriteEngine = createSQLRewriteEngine(
                 createSQLRouteResultForSelectEqualWithShardingEncryptor(), "SELECT id FROM table_z WHERE id=? AND name=?", Arrays.<Object>asList(1, "x"), false);
-        assertThat(rewriteEngine.generateSQL().getSql(), is("SELECT cipher FROM table_z WHERE plain = ? AND name=?"));
+        assertThat(rewriteEngine.generateSQL().getSql(), is("SELECT plain FROM table_z WHERE plain = ? AND name=?"));
         assertThat(getParameterBuilder(rewriteEngine).getParameters().get(0), is((Object) 1));
     }
     
@@ -1062,7 +1062,7 @@ public final class ShardingSQLRewriteEngineTest {
     public void assertRewriteSelectInWithShardingEncryptorWithParameterWithPlain() {
         SQLRewriteEngine rewriteEngine = createSQLRewriteEngine(
                 createSQLRouteResultForSelectInWithShardingEncryptorWithParameter(), "SELECT id FROM table_z WHERE id in (?, ?) or id = 3", Arrays.<Object>asList(1, 2), false);
-        assertThat(rewriteEngine.generateSQL(null, logicTableAndActualTables).getSql(), is("SELECT cipher FROM table_z WHERE plain IN (?, ?) or plain = '3'"));
+        assertThat(rewriteEngine.generateSQL(null, logicTableAndActualTables).getSql(), is("SELECT plain FROM table_z WHERE plain IN (?, ?) or plain = '3'"));
         assertThat(getParameterBuilder(rewriteEngine).getParameters().get(0), is((Object) 1));
         assertThat(getParameterBuilder(rewriteEngine).getParameters().get(1), is((Object) 2));
     }
diff --git a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/adapter/AbstractResultSetAdapter.java b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/adapter/AbstractResultSetAdapter.java
index 0110b8cdb8b..46cc402d947 100644
--- a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/adapter/AbstractResultSetAdapter.java
+++ b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/adapter/AbstractResultSetAdapter.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.shardingjdbc.jdbc.adapter;
 import com.google.common.base.Preconditions;
 import lombok.AccessLevel;
 import lombok.Getter;
+import org.apache.shardingsphere.core.constant.properties.ShardingPropertiesConstant;
 import org.apache.shardingsphere.core.route.SQLRouteResult;
 import org.apache.shardingsphere.core.rule.ShardingRule;
 import org.apache.shardingsphere.shardingjdbc.jdbc.adapter.executor.ForceExecuteCallback;
@@ -42,6 +43,7 @@ import java.util.Map;
  * Adapter for {@code ResultSet}.
  * 
  * @author zhangliang
+ * @author panjuan
  */
 public abstract class AbstractResultSetAdapter extends AbstractUnsupportedOperationResultSet {
     
@@ -70,10 +72,14 @@ public abstract class AbstractResultSetAdapter extends AbstractUnsupportedOperat
     
     @Override
     public final ResultSetMetaData getMetaData() throws SQLException {
-        return new ShardingResultSetMetaData(resultSets.get(0).getMetaData(), getShardingRule(), sqlRouteResult.getOptimizedStatement());
+        return new ShardingResultSetMetaData(resultSets.get(0).getMetaData(), getShardingRule(), sqlRouteResult.getOptimizedStatement(), logicAndActualColumns);
     }
     
     private Map<String, String> createLogicAndActualColumns() {
+        return isQueryWithCipherColumn() ? createLogicAndCipherColumns() : createLogicAndPlainColumns();
+    }
+    
+    private Map<String, String> createLogicAndCipherColumns() {
         Map<String, String> result = new LinkedHashMap<>();
         for (String each : sqlRouteResult.getOptimizedStatement().getTables().getTableNames()) {
             result.putAll(getShardingRule().getEncryptRule().getLogicAndCipherColumns(each));
@@ -81,12 +87,26 @@ public abstract class AbstractResultSetAdapter extends AbstractUnsupportedOperat
         return result;
     }
     
+    private Map<String, String> createLogicAndPlainColumns() {
+        Map<String, String> result = new LinkedHashMap<>();
+        for (String each : sqlRouteResult.getOptimizedStatement().getTables().getTableNames()) {
+            result.putAll(getShardingRule().getEncryptRule().getLogicAndPlainColumns(each));
+        }
+        return result;
+    }
+    
     private ShardingRule getShardingRule() {
         return statement instanceof ShardingPreparedStatement 
                 ? ((ShardingPreparedStatement) statement).getConnection().getRuntimeContext().getRule() 
                 : ((ShardingStatement) statement).getConnection().getRuntimeContext().getRule();
     }
     
+    private boolean isQueryWithCipherColumn() {
+        return statement instanceof ShardingPreparedStatement
+                ? ((ShardingPreparedStatement) statement).getConnection().getRuntimeContext().getProps().<Boolean>getValue(ShardingPropertiesConstant.QUERY_WITH_CIPHER_COLUMN)
+                : ((ShardingStatement) statement).getConnection().getRuntimeContext().getProps().<Boolean>getValue(ShardingPropertiesConstant.QUERY_WITH_CIPHER_COLUMN);
+    }
+    
     @Override
     public final int findColumn(final String columnLabel) throws SQLException {
         return resultSets.get(0).findColumn(getActualColumnLabel(columnLabel));
diff --git a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSet.java b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSet.java
index 50345dbbb8b..a2c4f4c4fdb 100644
--- a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSet.java
+++ b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSet.java
@@ -17,11 +17,13 @@
 
 package org.apache.shardingsphere.shardingjdbc.jdbc.core.resultset;
 
+import org.apache.shardingsphere.core.constant.properties.ShardingPropertiesConstant;
 import org.apache.shardingsphere.core.execute.sql.execute.result.QueryResult;
 import org.apache.shardingsphere.core.execute.sql.execute.result.StreamQueryResult;
 import org.apache.shardingsphere.core.merge.dql.iterator.IteratorStreamMergedResult;
 import org.apache.shardingsphere.core.optimize.api.statement.OptimizedStatement;
 import org.apache.shardingsphere.core.rule.EncryptRule;
+import org.apache.shardingsphere.shardingjdbc.jdbc.core.context.EncryptRuntimeContext;
 import org.apache.shardingsphere.shardingjdbc.jdbc.unsupported.AbstractUnsupportedOperationResultSet;
 
 import java.io.InputStream;
@@ -63,17 +65,21 @@ public final class EncryptResultSet extends AbstractUnsupportedOperationResultSe
     
     private final Map<String, String> logicAndActualColumns;
     
-    public EncryptResultSet(final EncryptRule encryptRule, final OptimizedStatement optimizedStatement, final Statement encryptStatement, final ResultSet resultSet) {
-        this.encryptRule = encryptRule;
+    public EncryptResultSet(final EncryptRuntimeContext encryptRuntimeContext, final OptimizedStatement optimizedStatement, final Statement encryptStatement, final ResultSet resultSet) {
+        this.encryptRule = encryptRuntimeContext.getRule();
         this.optimizedStatement = optimizedStatement;
         this.encryptStatement = encryptStatement;
         originalResultSet = resultSet;
         QueryResult queryResult = new StreamQueryResult(resultSet, encryptRule);
         this.resultSet = new IteratorStreamMergedResult(Collections.singletonList(queryResult));
-        logicAndActualColumns = createLogicAndActualColumns();
+        logicAndActualColumns = createLogicAndActualColumns(encryptRuntimeContext.getProps().<Boolean>getValue(ShardingPropertiesConstant.QUERY_WITH_CIPHER_COLUMN));
     }
     
-    private Map<String, String> createLogicAndActualColumns() {
+    private Map<String, String> createLogicAndActualColumns(final boolean isQueryWithCipherColumn) {
+        return isQueryWithCipherColumn ? createLogicAndCipherColumns() : createLogicAndPlainColumns();
+    }
+    
+    private Map<String, String> createLogicAndCipherColumns() {
         Map<String, String> result = new LinkedHashMap<>();
         for (String each : optimizedStatement.getTables().getTableNames()) {
             result.putAll(encryptRule.getLogicAndCipherColumns(each));
@@ -81,6 +87,14 @@ public final class EncryptResultSet extends AbstractUnsupportedOperationResultSe
         return result;
     }
     
+    private Map<String, String> createLogicAndPlainColumns() {
+        Map<String, String> result = new LinkedHashMap<>();
+        for (String each : optimizedStatement.getTables().getTableNames()) {
+            result.putAll(encryptRule.getLogicAndPlainColumns(each));
+        }
+        return result;
+    }
+    
     @Override
     public boolean next() throws SQLException {
         return resultSet.next();
@@ -357,7 +371,7 @@ public final class EncryptResultSet extends AbstractUnsupportedOperationResultSe
     
     @Override
     public ResultSetMetaData getMetaData() throws SQLException {
-        return new EncryptResultSetMetaData(originalResultSet.getMetaData(), encryptRule, optimizedStatement);
+        return new EncryptResultSetMetaData(originalResultSet.getMetaData(), encryptRule, optimizedStatement, logicAndActualColumns);
     }
     
     @Override
diff --git a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSetMetaData.java b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSetMetaData.java
index 4313e77dd94..31fea0591a7 100644
--- a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSetMetaData.java
+++ b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/EncryptResultSetMetaData.java
@@ -25,7 +25,6 @@ import org.apache.shardingsphere.shardingjdbc.jdbc.adapter.WrapperAdapter;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.util.Collection;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -45,19 +44,12 @@ public final class EncryptResultSetMetaData extends WrapperAdapter implements Re
     
     private final Map<String, String> logicAndActualColumns;
     
-    public EncryptResultSetMetaData(final ResultSetMetaData resultSetMetaData, final EncryptRule encryptRule, final OptimizedStatement optimizedStatement) {
+    public EncryptResultSetMetaData(final ResultSetMetaData resultSetMetaData, 
+                                    final EncryptRule encryptRule, final OptimizedStatement optimizedStatement, final Map<String, String> logicAndActualColumns) {
         this.resultSetMetaData = resultSetMetaData;
         this.encryptRule = encryptRule;
         this.optimizedStatement = optimizedStatement;
-        logicAndActualColumns = createLogicAndActualColumns();
-    }
-    
-    private Map<String, String> createLogicAndActualColumns() {
-        Map<String, String> result = new LinkedHashMap<>();
-        for (String each : optimizedStatement.getTables().getTableNames()) {
-            result.putAll(encryptRule.getLogicAndCipherColumns(each));
-        }
-        return result;
+        this.logicAndActualColumns = logicAndActualColumns;
     }
     
     @Override
diff --git a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetMetaData.java b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetMetaData.java
index 4f6d3cfb94b..fd7439e2b51 100644
--- a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetMetaData.java
+++ b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetMetaData.java
@@ -26,7 +26,6 @@ import org.apache.shardingsphere.shardingjdbc.jdbc.adapter.WrapperAdapter;
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
 import java.util.Collection;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -47,19 +46,12 @@ public final class ShardingResultSetMetaData extends WrapperAdapter implements R
     
     private final Map<String, String> logicAndActualColumns;
     
-    public ShardingResultSetMetaData(final ResultSetMetaData resultSetMetaData, final ShardingRule shardingRule, final OptimizedStatement optimizedStatement) {
+    public ShardingResultSetMetaData(final ResultSetMetaData resultSetMetaData, 
+                                     final ShardingRule shardingRule, final OptimizedStatement optimizedStatement, final Map<String, String> logicAndActualColumns) {
         this.resultSetMetaData = resultSetMetaData;
         this.shardingRule = shardingRule;
         this.optimizedStatement = optimizedStatement;
-        logicAndActualColumns = createLogicAndActualColumns();
-    }
-    
-    private Map<String, String> createLogicAndActualColumns() {
-        Map<String, String> result = new LinkedHashMap<>();
-        for (String each : optimizedStatement.getTables().getTableNames()) {
-            result.putAll(shardingRule.getEncryptRule().getLogicAndCipherColumns(each));
-        }
-        return result;
+        this.logicAndActualColumns = logicAndActualColumns;
     }
     
     @Override
diff --git a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptPreparedStatement.java b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptPreparedStatement.java
index f8fe3a17fda..3fe351cd428 100644
--- a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptPreparedStatement.java
+++ b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptPreparedStatement.java
@@ -99,7 +99,7 @@ public final class EncryptPreparedStatement extends AbstractShardingPreparedStat
             SQLUnit sqlUnit = getSQLUnit(sql);
             preparedStatement = preparedStatementGenerator.createPreparedStatement(sqlUnit.getSql());
             replaySetParameter(preparedStatement, sqlUnit.getParameters());
-            this.resultSet = new EncryptResultSet(preparedStatementGenerator.connection.getRuntimeContext().getRule(), optimizedStatement, this, preparedStatement.executeQuery());
+            this.resultSet = new EncryptResultSet(preparedStatementGenerator.connection.getRuntimeContext(), optimizedStatement, this, preparedStatement.executeQuery());
             return resultSet;
         } finally {
             clearParameters();
@@ -139,7 +139,7 @@ public final class EncryptPreparedStatement extends AbstractShardingPreparedStat
     
     private EncryptResultSet createEncryptResultSet(final PreparedStatement preparedStatement) throws SQLException {
         return null == preparedStatement.getResultSet() 
-                ? null : new EncryptResultSet(preparedStatementGenerator.connection.getRuntimeContext().getRule(), optimizedStatement, this, preparedStatement.getResultSet());
+                ? null : new EncryptResultSet(preparedStatementGenerator.connection.getRuntimeContext(), optimizedStatement, this, preparedStatement.getResultSet());
     }
     
     @Override
diff --git a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatement.java b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatement.java
index 13ae8d13994..61120e9d079 100644
--- a/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatement.java
+++ b/sharding-jdbc/sharding-jdbc-core/src/main/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatement.java
@@ -71,7 +71,7 @@ public final class EncryptStatement extends AbstractUnsupportedOperationStatemen
     @Override
     public ResultSet executeQuery(final String sql) throws SQLException {
         ResultSet resultSet = statement.executeQuery(getRewriteSQL(sql));
-        this.resultSet = new EncryptResultSet(connection.getRuntimeContext().getRule(), optimizedStatement, this, resultSet);
+        this.resultSet = new EncryptResultSet(connection.getRuntimeContext(), optimizedStatement, this, resultSet);
         return this.resultSet;
     }
     
@@ -148,7 +148,7 @@ public final class EncryptStatement extends AbstractUnsupportedOperationStatemen
     }
     
     private EncryptResultSet createEncryptResultSet(final Statement statement) throws SQLException {
-        return null == statement.getResultSet() ? null : new EncryptResultSet(connection.getRuntimeContext().getRule(), optimizedStatement, this, statement.getResultSet());
+        return null == statement.getResultSet() ? null : new EncryptResultSet(connection.getRuntimeContext(), optimizedStatement, this, statement.getResultSet());
     }
     
     @Override
diff --git a/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/common/base/AbstractEncryptJDBCDatabaseAndTableTest.java b/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/common/base/AbstractEncryptJDBCDatabaseAndTableTest.java
index beb2ccc4766..9eef55c4331 100644
--- a/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/common/base/AbstractEncryptJDBCDatabaseAndTableTest.java
+++ b/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/common/base/AbstractEncryptJDBCDatabaseAndTableTest.java
@@ -61,7 +61,7 @@ public abstract class AbstractEncryptJDBCDatabaseAndTableTest extends AbstractSQ
     private static Properties createProperties() {
         Properties result = new Properties();
         result.put(ShardingPropertiesConstant.SQL_SHOW.getKey(), true);
-        result.put(ShardingPropertiesConstant.QUERY_WITH_CIPHER_COLUMN, false);
+        result.put(ShardingPropertiesConstant.QUERY_WITH_CIPHER_COLUMN.getKey(), false);
         return result;
     }
     
diff --git a/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetTest.java b/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetTest.java
index df7d28df671..904a06ec236 100644
--- a/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetTest.java
+++ b/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/resultset/ShardingResultSetTest.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.shardingjdbc.jdbc.core.resultset;
 
 import com.google.common.base.Optional;
 import lombok.SneakyThrows;
+import org.apache.shardingsphere.core.constant.properties.ShardingProperties;
 import org.apache.shardingsphere.core.merge.MergedResult;
 import org.apache.shardingsphere.core.optimize.api.segment.Tables;
 import org.apache.shardingsphere.core.optimize.api.statement.OptimizedStatement;
@@ -49,6 +50,7 @@ import java.sql.Timestamp;
 import java.util.Calendar;
 import java.util.Collections;
 import java.util.List;
+import java.util.Properties;
 
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.CoreMatchers.is;
@@ -101,6 +103,7 @@ public final class ShardingResultSetTest {
         when(encryptRule.getShardingEncryptor(anyString(), anyString())).thenReturn(Optional.<ShardingEncryptor>absent());
         when(shardingRule.getEncryptRule()).thenReturn(encryptRule);
         when(runtimeContext.getRule()).thenReturn(shardingRule);
+        when(runtimeContext.getProps()).thenReturn(new ShardingProperties(new Properties()));
         when(shardingConnection.getRuntimeContext()).thenReturn(runtimeContext);
         ShardingStatement statement = mock(ShardingStatement.class);
         when(statement.getConnection()).thenReturn(shardingConnection);
diff --git a/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatementTest.java b/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatementTest.java
index 776398d4b50..b8f020851b0 100644
--- a/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatementTest.java
+++ b/sharding-jdbc/sharding-jdbc-core/src/test/java/org/apache/shardingsphere/shardingjdbc/jdbc/core/statement/EncryptStatementTest.java
@@ -50,6 +50,8 @@ public final class EncryptStatementTest extends AbstractEncryptJDBCDatabaseAndTa
     
     private static final String SELECT_SQL_WITH_PLAIN = "select id, pwd from t_encrypt where pwd = 'plainValue'";
     
+    private static final String SELECT_SQL_WITH_CIPHER = "select id, pwd from t_encrypt where pwd = 'plainValue'";
+    
     private static final String SELECT_SQL_TO_ASSERT = "select id, cipher_pwd, plain_pwd from t_encrypt";
     
     @Test
@@ -122,17 +124,32 @@ public final class EncryptStatementTest extends AbstractEncryptJDBCDatabaseAndTa
     
     @Test
     public void assertSelectWithMetaData() throws SQLException {
-        try (Statement statement = getEncryptConnection().createStatement()) {
+        try (Statement statement = getEncryptConnectionWithProps().createStatement()) {
             ResultSetMetaData metaData = statement.executeQuery(SELECT_SQL_WITH_STAR).getMetaData();
             assertThat(metaData.getColumnCount(), is(3));
             for (int i = 0; i < metaData.getColumnCount(); i++) {
                 assertThat(metaData.getColumnLabel(1), is("id"));
-                assertThat(metaData.getColumnLabel(2), is("pwd"));
-                assertThat(metaData.getColumnLabel(3), is("plain_pwd"));
+                assertThat(metaData.getColumnLabel(2), is("cipher_pwd"));
+                assertThat(metaData.getColumnLabel(3), is("pwd"));
             }
         }
     }
     
+    @Test
+    public void assertSelectWithCipherColumn() throws SQLException {
+        try (Statement statement = getEncryptConnection().createStatement()) {
+            ResultSet resultSet = statement.executeQuery(SELECT_SQL_WITH_CIPHER);
+            int count = 1;
+            List<Object> ids = Arrays.asList((Object) 1, 5);
+            while (resultSet.next()) {
+                assertThat(resultSet.getObject("id"), is(ids.get(count - 1)));
+                assertThat(resultSet.getObject("pwd"), is((Object) "decryptValue"));
+                count += 1;
+            }
+            assertThat(count - 1, is(ids.size()));
+        }
+    }
+    
     @Test
     public void assertSelectWithPlainColumn() throws SQLException {
         try (Statement statement = getEncryptConnectionWithProps().createStatement()) {
@@ -141,7 +158,7 @@ public final class EncryptStatementTest extends AbstractEncryptJDBCDatabaseAndTa
             List<Object> ids = Arrays.asList((Object) 1, 5);
             while (resultSet.next()) {
                 assertThat(resultSet.getObject("id"), is(ids.get(count - 1)));
-                assertThat(resultSet.getObject("pwd"), is((Object) "decryptValue"));
+                assertThat(resultSet.getObject("pwd"), is((Object) "plainValue"));
                 count += 1;
             }
             assertThat(count - 1, is(ids.size()));