You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by du...@apache.org on 2023/06/06 02:30:36 UTC

[shardingsphere] branch master updated: Fix encrypt ShorthandProjection expand with/ without quote (#26033)

This is an automated email from the ASF dual-hosted git repository.

duanzhengqiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new b5008ce5680 Fix encrypt ShorthandProjection expand with/ without quote (#26033)
b5008ce5680 is described below

commit b5008ce5680b471cd49b00c09aa25d18f90b3f38
Author: Chuxin Chen <ch...@qq.com>
AuthorDate: Tue Jun 6 10:30:27 2023 +0800

    Fix encrypt ShorthandProjection expand with/ without quote (#26033)
    
    * Fix encrypt ShorthandProjection expand quote
    
    * Fix encrypt ShorthandProjection expand quote
    
    * Fix encrypt ShorthandProjection expand quote
---
 .../EncryptCreateTableTokenGenerator.java          | 14 +++--
 .../EncryptIndexColumnTokenGenerator.java          |  9 +--
 .../EncryptOrderByItemTokenGenerator.java          | 11 ++--
 .../EncryptPredicateColumnTokenGenerator.java      | 12 ++--
 .../generator/EncryptProjectionTokenGenerator.java | 29 ++++++----
 .../generator/InsertCipherNameTokenGenerator.java  |  4 +-
 .../segment/select/projection/Projection.java      |  6 +-
 .../select/projection/engine/ProjectionEngine.java | 33 ++++++-----
 .../impl/AggregationDistinctProjection.java        |  3 +-
 .../projection/impl/AggregationProjection.java     |  3 +-
 .../select/projection/impl/ColumnProjection.java   | 41 +++++++++++---
 .../select/projection/impl/DerivedProjection.java  |  3 +-
 .../projection/impl/ExpressionProjection.java      |  3 +-
 .../projection/impl/ParameterMarkerProjection.java |  3 +-
 .../projection/impl/ShorthandProjection.java       |  5 +-
 .../select/projection/impl/SubqueryProjection.java |  3 +-
 .../projection/engine/ProjectionEngineTest.java    | 65 ++++++++++++----------
 .../pojo/generic/SubstitutableColumnNameToken.java |  4 +-
 .../generic/SubstitutableColumnNameTokenTest.java  |  6 +-
 .../common/value/identifier/IdentifierValue.java   |  2 +
 .../dml/select/select-subquery.xml                 |  2 +-
 21 files changed, 165 insertions(+), 96 deletions(-)

diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptCreateTableTokenGenerator.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptCreateTableTokenGenerator.java
index c437cd7d927..34c146ccc4d 100644
--- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptCreateTableTokenGenerator.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptCreateTableTokenGenerator.java
@@ -29,6 +29,7 @@ import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.SQLToken;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic.RemoveToken;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic.SubstitutableColumnNameToken;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.ddl.column.ColumnDefinitionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -80,22 +81,25 @@ public final class EncryptCreateTableTokenGenerator implements CollectionSQLToke
     }
     
     private SQLToken getCipherColumnToken(final String tableName, final String columnName, final ColumnDefinitionSegment column, final int stopIndex) {
-        return new SubstitutableColumnNameToken(stopIndex + 1, column.getColumnName().getStopIndex(), getColumnProjections(encryptRule.getCipherColumn(tableName, columnName)));
+        return new SubstitutableColumnNameToken(stopIndex + 1, column.getColumnName().getStopIndex(), getColumnProjections(new IdentifierValue(encryptRule.getCipherColumn(tableName, columnName),
+                column.getColumnName().getIdentifier().getQuoteCharacter())));
     }
     
     private Optional<? extends SQLToken> getAssistedQueryColumnToken(final String tableName, final String columnName, final ColumnDefinitionSegment column,
                                                                      final int stopIndex, final boolean lastColumn) {
         Optional<String> assistedQueryColumn = encryptRule.findAssistedQueryColumn(tableName, columnName);
-        return assistedQueryColumn.map(optional -> new SubstitutableColumnNameToken(stopIndex + 1, column.getColumnName().getStopIndex(), getColumnProjections(optional), lastColumn));
+        return assistedQueryColumn.map(optional -> new SubstitutableColumnNameToken(stopIndex + 1, column.getColumnName().getStopIndex(),
+                getColumnProjections(new IdentifierValue(optional, column.getColumnName().getIdentifier().getQuoteCharacter())), lastColumn));
     }
     
     private Optional<? extends SQLToken> getLikeQueryColumnToken(final String tableName, final String columnName, final ColumnDefinitionSegment column,
                                                                  final int stopIndex, final boolean lastColumn) {
         Optional<String> likeQueryColumn = encryptRule.findLikeQueryColumn(tableName, columnName);
-        return likeQueryColumn.map(optional -> new SubstitutableColumnNameToken(stopIndex + 1, column.getColumnName().getStopIndex(), getColumnProjections(optional), lastColumn));
+        return likeQueryColumn.map(optional -> new SubstitutableColumnNameToken(stopIndex + 1, column.getColumnName().getStopIndex(),
+                getColumnProjections(new IdentifierValue(optional, column.getColumnName().getIdentifier().getQuoteCharacter())), lastColumn));
     }
     
-    private Collection<ColumnProjection> getColumnProjections(final String columnName) {
-        return Collections.singletonList(new ColumnProjection(null, columnName, null));
+    private Collection<ColumnProjection> getColumnProjections(final IdentifierValue columnIdentifier) {
+        return Collections.singletonList(new ColumnProjection(null, columnIdentifier, null));
     }
 }
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptIndexColumnTokenGenerator.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptIndexColumnTokenGenerator.java
index 1cda09c5565..6846c421df4 100644
--- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptIndexColumnTokenGenerator.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptIndexColumnTokenGenerator.java
@@ -29,6 +29,7 @@ import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.SQLToken;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic.SubstitutableColumnNameToken;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.QuoteCharacter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -72,17 +73,17 @@ public final class EncryptIndexColumnTokenGenerator implements CollectionSQLToke
     }
     
     private Optional<SQLToken> getAssistedQueryColumnToken(final int startIndex, final int stopIndex, final String columnName, final QuoteCharacter quoteCharacter) {
-        Collection<ColumnProjection> columnProjections = getColumnProjections(columnName);
+        Collection<ColumnProjection> columnProjections = getColumnProjections(columnName, quoteCharacter);
         return Optional.of(new SubstitutableColumnNameToken(startIndex, stopIndex, columnProjections, quoteCharacter, Collections.emptyList()));
     }
     
     private Optional<SQLToken> getCipherColumnToken(final String tableName, final int startIndex, final int stopIndex, final String columnName, final QuoteCharacter quoteCharacter) {
         String cipherColumn = encryptRule.getCipherColumn(tableName, columnName);
-        Collection<ColumnProjection> columnProjections = getColumnProjections(cipherColumn);
+        Collection<ColumnProjection> columnProjections = getColumnProjections(cipherColumn, quoteCharacter);
         return Optional.of(new SubstitutableColumnNameToken(startIndex, stopIndex, columnProjections, quoteCharacter, Collections.emptyList()));
     }
     
-    private Collection<ColumnProjection> getColumnProjections(final String columnName) {
-        return Collections.singletonList(new ColumnProjection(null, columnName, null));
+    private Collection<ColumnProjection> getColumnProjections(final String columnName, final QuoteCharacter quoteCharacter) {
+        return Collections.singletonList(new ColumnProjection(null, new IdentifierValue(columnName, quoteCharacter), null));
     }
 }
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java
index a6016f85e79..8aaf70eb0c5 100644
--- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java
@@ -31,8 +31,10 @@ import org.apache.shardingsphere.infra.rewrite.sql.token.generator.CollectionSQL
 import org.apache.shardingsphere.infra.rewrite.sql.token.generator.aware.SchemaMetaDataAware;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.SQLToken;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic.SubstitutableColumnNameToken;
+import org.apache.shardingsphere.sql.parser.sql.common.enums.QuoteCharacter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.order.item.ColumnOrderByItemSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -84,8 +86,9 @@ public final class EncryptOrderByItemTokenGenerator implements CollectionSQLToke
             int startIndex = column.getOwner().isPresent() ? column.getOwner().get().getStopIndex() + 2 : column.getStartIndex();
             int stopIndex = column.getStopIndex();
             Optional<String> assistedQueryColumn = encryptTable.get().findAssistedQueryColumn(column.getIdentifier().getValue());
-            SubstitutableColumnNameToken encryptColumnNameToken = assistedQueryColumn.map(optional -> new SubstitutableColumnNameToken(startIndex, stopIndex, createColumnProjections(optional)))
-                    .orElseGet(() -> new SubstitutableColumnNameToken(startIndex, stopIndex, createColumnProjections(encryptTable.get().getCipherColumn(column.getIdentifier().getValue()))));
+            SubstitutableColumnNameToken encryptColumnNameToken = assistedQueryColumn.map(optional -> new SubstitutableColumnNameToken(startIndex, stopIndex,
+                    createColumnProjections(optional, column.getIdentifier().getQuoteCharacter()))).orElseGet(() -> new SubstitutableColumnNameToken(startIndex, stopIndex,
+                            createColumnProjections(encryptTable.get().getCipherColumn(column.getIdentifier().getValue()), column.getIdentifier().getQuoteCharacter())));
             result.add(encryptColumnNameToken);
         }
         return result;
@@ -121,7 +124,7 @@ public final class EncryptOrderByItemTokenGenerator implements CollectionSQLToke
         return false;
     }
     
-    private Collection<ColumnProjection> createColumnProjections(final String columnName) {
-        return Collections.singletonList(new ColumnProjection(null, columnName, null));
+    private Collection<ColumnProjection> createColumnProjections(final String columnName, final QuoteCharacter quoteCharacter) {
+        return Collections.singletonList(new ColumnProjection(null, new IdentifierValue(columnName, quoteCharacter), null));
     }
 }
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptPredicateColumnTokenGenerator.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptPredicateColumnTokenGenerator.java
index 295ec9d3cad..ff99bafa75d 100644
--- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptPredicateColumnTokenGenerator.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptPredicateColumnTokenGenerator.java
@@ -32,12 +32,14 @@ import org.apache.shardingsphere.infra.rewrite.sql.token.generator.aware.SchemaM
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.SQLToken;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic.SubstitutableColumnNameToken;
 import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
+import org.apache.shardingsphere.sql.parser.sql.common.enums.QuoteCharacter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BinaryOperationExpression;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.util.ExpressionExtractUtils;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -98,10 +100,12 @@ public final class EncryptPredicateColumnTokenGenerator implements CollectionSQL
         if (includesLike(whereSegments, columnSegment)) {
             Optional<String> likeQueryColumn = encryptTable.findLikeQueryColumn(logicColumn);
             ShardingSpherePreconditions.checkState(likeQueryColumn.isPresent(), () -> new UnsupportedEncryptSQLException("LIKE"));
-            return new SubstitutableColumnNameToken(startIndex, stopIndex, createColumnProjections(likeQueryColumn.get()));
+            return new SubstitutableColumnNameToken(startIndex, stopIndex, createColumnProjections(likeQueryColumn.get(), columnSegment.getIdentifier().getQuoteCharacter()));
         }
         Collection<ColumnProjection> columnProjections =
-                encryptTable.findAssistedQueryColumn(logicColumn).map(this::createColumnProjections).orElseGet(() -> createColumnProjections(encryptTable.getCipherColumn(logicColumn)));
+                encryptTable.findAssistedQueryColumn(logicColumn).map(optional -> createColumnProjections(optional, columnSegment.getIdentifier().getQuoteCharacter()))
+                        .orElseGet(() -> createColumnProjections(encryptTable.getCipherColumn(logicColumn),
+                                columnSegment.getIdentifier().getQuoteCharacter()));
         return new SubstitutableColumnNameToken(startIndex, stopIndex, columnProjections);
     }
     
@@ -131,7 +135,7 @@ public final class EncryptPredicateColumnTokenGenerator implements CollectionSQL
         return columnSegment instanceof ColumnSegment && columnSegment.getStartIndex() == targetColumnSegment.getStartIndex() && columnSegment.getStopIndex() == targetColumnSegment.getStopIndex();
     }
     
-    private Collection<ColumnProjection> createColumnProjections(final String columnName) {
-        return Collections.singletonList(new ColumnProjection(null, columnName, null));
+    private Collection<ColumnProjection> createColumnProjections(final String columnName, final QuoteCharacter quoteCharacter) {
+        return Collections.singletonList(new ColumnProjection(null, new IdentifierValue(columnName, quoteCharacter), null));
     }
 }
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
index e0791152a70..19904b6c759 100644
--- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
@@ -38,6 +38,9 @@ import org.apache.shardingsphere.sql.parser.sql.common.enums.SubqueryType;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ColumnProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Collection;
 import java.util.LinkedHashSet;
@@ -113,7 +116,7 @@ public final class EncryptProjectionTokenGenerator implements CollectionSQLToken
         for (ColumnProjection each : columnProjections) {
             String tableName = columnTableNames.get(each.getExpression());
             if (null == tableName || !encryptRule.findStandardEncryptor(tableName, each.getName()).isPresent()) {
-                projections.add(new ColumnProjection(each.getOwner(), each.getName(), each.getAlias().orElse(null)));
+                projections.add(new ColumnProjection(each.getOwnerIdentifier(), each.getNameIdentifier(), each.getAlias().isPresent() ? each.getAliasIdentifier() : null));
             } else {
                 projections.addAll(generateProjections(tableName, each, subqueryType, true, segment));
             }
@@ -125,8 +128,8 @@ public final class EncryptProjectionTokenGenerator implements CollectionSQLToken
     }
     
     private ColumnProjection buildColumnProjection(final ColumnProjectionSegment segment) {
-        String owner = segment.getColumn().getOwner().map(optional -> optional.getIdentifier().getValue()).orElse(null);
-        return new ColumnProjection(owner, segment.getColumn().getIdentifier().getValue(), segment.getAliasName().orElse(null));
+        IdentifierValue owner = segment.getColumn().getOwner().map(OwnerSegment::getIdentifier).orElse(null);
+        return new ColumnProjection(owner, segment.getColumn().getIdentifier(), segment.getAliasName().isPresent() ? segment.getAlias().map(AliasSegment::getIdentifier).orElse(null) : null);
     }
     
     private Map<String, String> getColumnTableNames(final SelectStatementContext selectStatementContext) {
@@ -163,36 +166,40 @@ public final class EncryptProjectionTokenGenerator implements CollectionSQLToken
         if (shorthand || null == column.getOwner()) {
             return column;
         }
-        return new ColumnProjection(null, column.getName(), column.getAlias().isPresent() ? column.getAlias().get() : null);
+        return new ColumnProjection(null, column.getNameIdentifier(), column.getAlias().isPresent() ? column.getAliasIdentifier() : null);
     }
     
     private ColumnProjection generatePredicateSubqueryProjection(final String tableName, final ColumnProjection column) {
         Optional<String> assistedQueryColumn = encryptRule.findAssistedQueryColumn(tableName, column.getName());
         if (assistedQueryColumn.isPresent()) {
-            return new ColumnProjection(column.getOwner(), assistedQueryColumn.get(), null);
+            return new ColumnProjection(column.getOwnerIdentifier(), new IdentifierValue(assistedQueryColumn.get(), column.getNameIdentifier().getQuoteCharacter()), null);
         }
         String cipherColumn = encryptRule.getCipherColumn(tableName, column.getName());
-        return new ColumnProjection(column.getOwner(), cipherColumn, null);
+        return new ColumnProjection(column.getOwnerIdentifier(), new IdentifierValue(cipherColumn, column.getNameIdentifier().getQuoteCharacter()), null);
     }
     
     private Collection<ColumnProjection> generateTableSubqueryProjections(final String tableName, final ColumnProjection column, final boolean shorthand) {
         Collection<ColumnProjection> result = new LinkedList<>();
-        result.add(distinctOwner(new ColumnProjection(column.getOwner(), encryptRule.getCipherColumn(tableName, column.getName()), null), shorthand));
+        result.add(distinctOwner(new ColumnProjection(column.getOwnerIdentifier(), new IdentifierValue(encryptRule.getCipherColumn(tableName, column.getName()),
+                column.getNameIdentifier().getQuoteCharacter()), null), shorthand));
         Optional<String> assistedQueryColumn = encryptRule.findAssistedQueryColumn(tableName, column.getName());
-        assistedQueryColumn.ifPresent(optional -> result.add(new ColumnProjection(column.getOwner(), optional, null)));
+        assistedQueryColumn.ifPresent(optional -> result.add(new ColumnProjection(column.getOwnerIdentifier(), new IdentifierValue(optional, column.getNameIdentifier().getQuoteCharacter()), null)));
         return result;
     }
     
     private Collection<ColumnProjection> generateExistsSubqueryProjections(final String tableName, final ColumnProjection column, final boolean shorthand) {
         Collection<ColumnProjection> result = new LinkedList<>();
-        result.add(distinctOwner(new ColumnProjection(column.getOwner(), encryptRule.getCipherColumn(tableName, column.getName()), null), shorthand));
+        result.add(distinctOwner(new ColumnProjection(column.getOwnerIdentifier(), new IdentifierValue(encryptRule.getCipherColumn(tableName, column.getName()),
+                column.getNameIdentifier().getQuoteCharacter()), null), shorthand));
         return result;
     }
     
     private ColumnProjection generateCommonProjection(final String tableName, final ColumnProjection column, final ShorthandProjectionSegment segment) {
         String encryptColumnName = getEncryptColumnName(tableName, column.getName());
-        String owner = null == segment || !segment.getOwner().isPresent() ? column.getOwner() : segment.getOwner().get().getIdentifier().getValue();
-        return new ColumnProjection(owner, encryptColumnName, column.getAlias().orElse(column.getName()));
+        IdentifierValue owner = (null == segment || !segment.getOwner().isPresent()) ? column.getOwnerIdentifier() : segment.getOwner().get().getIdentifier();
+        return new ColumnProjection(owner, new IdentifierValue(encryptColumnName, column.getNameIdentifier().getQuoteCharacter()), column.getAlias().isPresent()
+                ? column.getAliasIdentifier()
+                : column.getNameIdentifier());
     }
     
     private String getEncryptColumnName(final String tableName, final String logicEncryptColumnName) {
diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/InsertCipherNameTokenGenerator.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/InsertCipherNameTokenGenerator.java
index a473d7bbde2..ba458e4577a 100644
--- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/InsertCipherNameTokenGenerator.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/InsertCipherNameTokenGenerator.java
@@ -29,6 +29,7 @@ import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.SQLToken;
 import org.apache.shardingsphere.infra.rewrite.sql.token.pojo.generic.SubstitutableColumnNameToken;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.InsertColumnsSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -61,7 +62,8 @@ public final class InsertCipherNameTokenGenerator implements CollectionSQLTokenG
         Collection<SQLToken> result = new LinkedList<>();
         for (ColumnSegment each : sqlSegment.get().getColumns()) {
             if (logicAndCipherColumns.containsKey(each.getIdentifier().getValue())) {
-                Collection<ColumnProjection> projections = Collections.singletonList(new ColumnProjection(null, logicAndCipherColumns.get(each.getIdentifier().getValue()), null));
+                Collection<ColumnProjection> projections = Collections.singletonList(new ColumnProjection(null, new IdentifierValue(logicAndCipherColumns.get(each.getIdentifier().getValue()),
+                        each.getIdentifier().getQuoteCharacter()), null));
                 result.add(new SubstitutableColumnNameToken(each.getStartIndex(), each.getStopIndex(), projections));
             }
         }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/Projection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/Projection.java
index 5b58c4c25f9..fcdca992712 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/Projection.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/Projection.java
@@ -17,6 +17,8 @@
 
 package org.apache.shardingsphere.infra.binder.segment.select.projection;
 
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
+
 import java.util.Optional;
 
 /**
@@ -48,8 +50,8 @@ public interface Projection {
     /**
      * Clone with owner.
      * 
-     * @param ownerName owner name
+     * @param ownerIdentifier owner identifier
      * @return new projection
      */
-    Projection cloneWithOwner(String ownerName);
+    Projection cloneWithOwner(IdentifierValue ownerIdentifier);
 }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngine.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngine.java
index da5e37b9642..2f1eb8fe1d1 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngine.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngine.java
@@ -46,11 +46,14 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.Expressi
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ShorthandProjectionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.SubqueryProjectionSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.AliasSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.JoinTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SubqueryTableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.TableSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -119,17 +122,19 @@ public final class ProjectionEngine {
     }
     
     private ShorthandProjection createProjection(final TableSegment table, final ShorthandProjectionSegment projectionSegment) {
-        String owner = projectionSegment.getOwner().map(optional -> optional.getIdentifier().getValue()).orElse(null);
+        IdentifierValue owner = projectionSegment.getOwner().map(OwnerSegment::getIdentifier).orElse(null);
         Collection<Projection> projections = new LinkedHashSet<>();
         projections.addAll(getShorthandColumnsFromSimpleTableSegment(table, owner));
         projections.addAll(getShorthandColumnsFromSubqueryTableSegment(table));
         projections.addAll(getShorthandColumnsFromJoinTableSegment(table, owner, projectionSegment));
-        return new ShorthandProjection(owner, projections);
+        return new ShorthandProjection(null == owner ? null : owner.getValue(), projections);
     }
     
     private ColumnProjection createProjection(final ColumnProjectionSegment projectionSegment) {
-        String owner = projectionSegment.getColumn().getOwner().isPresent() ? projectionSegment.getColumn().getOwner().get().getIdentifier().getValue() : null;
-        return new ColumnProjection(owner, projectionSegment.getColumn().getIdentifier().getValue(), projectionSegment.getAliasName().orElse(null));
+        IdentifierValue owner = projectionSegment.getColumn().getOwner().isPresent() ? projectionSegment.getColumn().getOwner().get().getIdentifier() : null;
+        return new ColumnProjection(owner, projectionSegment.getColumn().getIdentifier(), projectionSegment.getAliasName().isPresent()
+                ? projectionSegment.getAlias().map(AliasSegment::getIdentifier).orElse(null)
+                : null);
     }
     
     private ExpressionProjection createProjection(final ExpressionProjectionSegment projectionSegment) {
@@ -157,7 +162,7 @@ public final class ProjectionEngine {
         return result;
     }
     
-    private Collection<ColumnProjection> getShorthandColumnsFromSimpleTableSegment(final TableSegment table, final String owner) {
+    private Collection<ColumnProjection> getShorthandColumnsFromSimpleTableSegment(final TableSegment table, final IdentifierValue owner) {
         if (!(table instanceof SimpleTableSegment)) {
             return Collections.emptyList();
         }
@@ -169,9 +174,10 @@ public final class ProjectionEngine {
         ShardingSpherePreconditions.checkNotNull(schema, () -> new SchemaNotFoundException(schemaName));
         Collection<ColumnProjection> result = new LinkedList<>();
         if (null == owner) {
-            schema.getVisibleColumnNames(tableName).stream().map(each -> new ColumnProjection(tableAlias, each, null)).forEach(result::add);
-        } else if (owner.equalsIgnoreCase(tableAlias)) {
-            schema.getVisibleColumnNames(tableName).stream().map(each -> new ColumnProjection(owner, each, null)).forEach(result::add);
+            schema.getVisibleColumnNames(tableName).stream().map(each -> new ColumnProjection(table.getAlias().map(AliasSegment::getIdentifier)
+                    .orElse(((SimpleTableSegment) table).getTableName().getIdentifier()), new IdentifierValue(each, databaseType.getQuoteCharacter()), null)).forEach(result::add);
+        } else if (owner.getValue().equalsIgnoreCase(tableAlias)) {
+            schema.getVisibleColumnNames(tableName).stream().map(each -> new ColumnProjection(owner, new IdentifierValue(each, databaseType.getQuoteCharacter()), null)).forEach(result::add);
         }
         return result;
     }
@@ -183,12 +189,11 @@ public final class ProjectionEngine {
         SelectStatement subSelectStatement = ((SubqueryTableSegment) table).getSubquery().getSelect();
         Collection<Projection> projections = subSelectStatement.getProjections().getProjections().stream().map(each -> createProjection(subSelectStatement.getFrom(), each).orElse(null))
                 .filter(Objects::nonNull).collect(Collectors.toList());
-        String subqueryTableAlias = table.getAliasName().orElse(null);
-        return getSubqueryTableActualProjections(projections, subqueryTableAlias);
+        return getSubqueryTableActualProjections(projections, table.getAlias().map(AliasSegment::getIdentifier).orElse(null));
     }
     
-    private Collection<Projection> getSubqueryTableActualProjections(final Collection<Projection> projections, final String subqueryTableAlias) {
-        if (Strings.isNullOrEmpty(subqueryTableAlias)) {
+    private Collection<Projection> getSubqueryTableActualProjections(final Collection<Projection> projections, final IdentifierValue subqueryTableAlias) {
+        if (null == subqueryTableAlias || Strings.isNullOrEmpty(subqueryTableAlias.getValue())) {
             return getActualProjections(projections);
         }
         Collection<Projection> result = new LinkedList<>();
@@ -202,7 +207,7 @@ public final class ProjectionEngine {
         return result;
     }
     
-    private Collection<Projection> getShorthandColumnsFromJoinTableSegment(final TableSegment table, final String owner, final ProjectionSegment projectionSegment) {
+    private Collection<Projection> getShorthandColumnsFromJoinTableSegment(final TableSegment table, final IdentifierValue owner, final ProjectionSegment projectionSegment) {
         if (!(table instanceof JoinTableSegment)) {
             return Collections.emptyList();
         }
@@ -211,7 +216,7 @@ public final class ProjectionEngine {
         Collection<Projection> remainingProjections = new LinkedList<>();
         for (Projection each : getOriginalProjections(joinTable, projectionSegment)) {
             Collection<Projection> actualProjections = getActualProjections(Collections.singletonList(each));
-            if (joinTable.getUsing().isEmpty() && !joinTable.isNatural() || null != owner && each.getExpression().contains(owner)) {
+            if (joinTable.getUsing().isEmpty() && !joinTable.isNatural() || null != owner && each.getExpression().contains(owner.getValue())) {
                 result.addAll(actualProjections);
             } else {
                 remainingProjections.addAll(actualProjections);
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationDistinctProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationDistinctProjection.java
index 0d9635f8701..d3651f0966a 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationDistinctProjection.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationDistinctProjection.java
@@ -21,6 +21,7 @@ import lombok.Getter;
 import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection;
 import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 /**
  * Aggregation distinct projection.
@@ -52,7 +53,7 @@ public final class AggregationDistinctProjection extends AggregationProjection {
     }
     
     @Override
-    public Projection cloneWithOwner(final String ownerName) {
+    public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) {
         // TODO replace column owner when AggregationDistinctProjection contains owner
         return new AggregationDistinctProjection(startIndex, stopIndex, getType(), getInnerExpression(), getAlias().orElse(null), distinctInnerExpression, getDatabaseType());
     }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationProjection.java
index 7a479b9cf92..f91ca5d9d1f 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationProjection.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/AggregationProjection.java
@@ -26,6 +26,7 @@ import org.apache.shardingsphere.infra.binder.segment.select.projection.Projecti
 import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.database.type.SchemaSupportedDatabaseType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -74,7 +75,7 @@ public class AggregationProjection implements Projection {
     }
     
     @Override
-    public Projection cloneWithOwner(final String ownerName) {
+    public Projection cloneWithOwner(final IdentifierValue owner) {
         // TODO replace column owner when AggregationProjection contains owner
         AggregationProjection result = new AggregationProjection(type, innerExpression, alias, databaseType);
         result.setIndex(index);
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ColumnProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ColumnProjection.java
index 43702fda063..65b074d0a48 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ColumnProjection.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ColumnProjection.java
@@ -22,6 +22,8 @@ import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection;
+import org.apache.shardingsphere.sql.parser.sql.common.enums.QuoteCharacter;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Optional;
 
@@ -34,29 +36,52 @@ import java.util.Optional;
 @ToString
 public final class ColumnProjection implements Projection {
     
-    private final String owner;
+    private final IdentifierValue ownerIdentifier;
     
-    private final String name;
+    private final IdentifierValue nameIdentifier;
     
-    private final String alias;
+    private final IdentifierValue aliasIdentifier;
+    
+    public ColumnProjection(final String owner, final String name, final String alias) {
+        this(null == owner ? null : new IdentifierValue(owner, QuoteCharacter.NONE), new IdentifierValue(name, QuoteCharacter.NONE),
+                null == alias ? null : new IdentifierValue(alias, QuoteCharacter.NONE));
+    }
+    
+    /**
+     * Get column name.
+     * 
+     * @return column name
+     */
+    public String getName() {
+        return nameIdentifier.getValue();
+    }
+    
+    /**
+     * Get owner.
+     * 
+     * @return owner
+     */
+    public String getOwner() {
+        return null == ownerIdentifier ? null : ownerIdentifier.getValue();
+    }
     
     @Override
     public String getExpression() {
-        return null == owner ? name : owner + "." + name;
+        return null == getOwner() ? getName() : getOwner() + "." + getName();
     }
     
     @Override
     public String getColumnLabel() {
-        return getAlias().orElse(name);
+        return getAlias().orElse(getName());
     }
     
     @Override
     public Optional<String> getAlias() {
-        return Optional.ofNullable(alias);
+        return Optional.ofNullable(aliasIdentifier).map(IdentifierValue::getValue);
     }
     
     @Override
-    public Projection cloneWithOwner(final String ownerName) {
-        return new ColumnProjection(ownerName, name, alias);
+    public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) {
+        return new ColumnProjection(ownerIdentifier, nameIdentifier, aliasIdentifier);
     }
 }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/DerivedProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/DerivedProjection.java
index 05d75a2e904..f05b47aaf39 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/DerivedProjection.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/DerivedProjection.java
@@ -23,6 +23,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.SQLSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Optional;
 
@@ -52,7 +53,7 @@ public final class DerivedProjection implements Projection {
     }
     
     @Override
-    public Projection cloneWithOwner(final String ownerName) {
+    public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) {
         return new DerivedProjection(expression, alias, derivedProjectionSegment);
     }
 }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ExpressionProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ExpressionProjection.java
index 97d9199f7f3..91ec030aac4 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ExpressionProjection.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ExpressionProjection.java
@@ -22,6 +22,7 @@ import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Optional;
 
@@ -49,7 +50,7 @@ public final class ExpressionProjection implements Projection {
     }
     
     @Override
-    public Projection cloneWithOwner(final String ownerName) {
+    public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) {
         // TODO replace column owner when ExpressionProjection contains owner
         return new ExpressionProjection(expression, alias);
     }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ParameterMarkerProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ParameterMarkerProjection.java
index 0a6b452c7e7..3c5609ac769 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ParameterMarkerProjection.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ParameterMarkerProjection.java
@@ -23,6 +23,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.ParameterMarkerType;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Optional;
 
@@ -57,7 +58,7 @@ public final class ParameterMarkerProjection implements Projection {
     }
     
     @Override
-    public Projection cloneWithOwner(final String ownerName) {
+    public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) {
         return new ParameterMarkerProjection(parameterMarkerIndex, parameterMarkerType, alias);
     }
 }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ShorthandProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ShorthandProjection.java
index 9640828101c..f503f04fa32 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ShorthandProjection.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/ShorthandProjection.java
@@ -23,6 +23,7 @@ import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Collection;
 import java.util.LinkedList;
@@ -81,7 +82,7 @@ public final class ShorthandProjection implements Projection {
     }
     
     @Override
-    public Projection cloneWithOwner(final String ownerName) {
-        return new ShorthandProjection(ownerName, actualColumns);
+    public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) {
+        return new ShorthandProjection(ownerIdentifier.getValue(), actualColumns);
     }
 }
diff --git a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/SubqueryProjection.java b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/SubqueryProjection.java
index 15769e62a27..2c88e929214 100644
--- a/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/SubqueryProjection.java
+++ b/infra/binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/select/projection/impl/SubqueryProjection.java
@@ -22,6 +22,7 @@ import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 import org.apache.shardingsphere.infra.binder.segment.select.projection.Projection;
+import org.apache.shardingsphere.sql.parser.sql.common.value.identifier.IdentifierValue;
 
 import java.util.Optional;
 
@@ -49,7 +50,7 @@ public final class SubqueryProjection implements Projection {
     }
     
     @Override
-    public Projection cloneWithOwner(final String ownerName) {
+    public Projection cloneWithOwner(final IdentifierValue ownerIdentifier) {
         return new SubqueryProjection(expression, alias);
     }
 }
diff --git a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngineTest.java b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngineTest.java
index e8488eb6c2e..5b9c6a11f00 100644
--- a/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngineTest.java
+++ b/infra/binder/src/test/java/org/apache/shardingsphere/infra/binder/segment/select/projection/engine/ProjectionEngineTest.java
@@ -31,6 +31,7 @@ import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSp
 import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.AggregationType;
 import org.apache.shardingsphere.sql.parser.sql.common.enums.JoinType;
+import org.apache.shardingsphere.sql.parser.sql.common.enums.QuoteCharacter;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.complex.CommonExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
@@ -102,6 +103,7 @@ class ProjectionEngineTest {
     void assertCreateProjectionWhenProjectionSegmentInstanceOfShorthandProjectionSegmentAndDuplicateTableSegment() {
         SimpleTableSegment table = new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order")));
         when(schema.getVisibleColumnNames("t_order")).thenReturn(Arrays.asList("order_id", "content"));
+        when(databaseType.getQuoteCharacter()).thenReturn(QuoteCharacter.NONE);
         Optional<Projection> actual = new ProjectionEngine(DefaultDatabase.LOGIC_NAME,
                 Collections.singletonMap(DefaultDatabase.LOGIC_NAME, schema), databaseType).createProjection(table, new ShorthandProjectionSegment(0, 0));
         assertTrue(actual.isPresent());
@@ -181,11 +183,12 @@ class ProjectionEngineTest {
     
     @Test
     void assertCreateProjectionWhenProjectionSegmentInstanceOfShorthandProjectionSegmentAndJoinTableSegment() {
-        SimpleTableSegment ordersTableSegment = new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order")));
         when(schema.getVisibleColumnNames("t_order")).thenReturn(Arrays.asList("order_id", "customer_id"));
+        when(databaseType.getQuoteCharacter()).thenReturn(QuoteCharacter.NONE);
         SimpleTableSegment customersTableSegment = new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_customer")));
         when(schema.getVisibleColumnNames("t_customer")).thenReturn(Collections.singletonList("customer_id"));
         JoinTableSegment table = new JoinTableSegment();
+        SimpleTableSegment ordersTableSegment = new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order")));
         table.setLeft(ordersTableSegment);
         table.setRight(customersTableSegment);
         table.setCondition(new CommonExpressionSegment(0, 0, "t_order.customer_id=t_customer.customer_id"));
@@ -277,7 +280,7 @@ class ProjectionEngineTest {
         assertTrue(actual.isPresent());
         assertThat(actual.get(), instanceOf(ShorthandProjection.class));
         assertThat(((ShorthandProjection) actual.get()).getActualColumns().size(), is(6));
-        assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(crateExpectedColumnsWithOwner()));
+        assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(crateExpectedColumnsWithOwner(TypedSPILoader.getService(DatabaseType.class, "PostgreSQL"))));
     }
     
     @Test
@@ -290,7 +293,7 @@ class ProjectionEngineTest {
         assertTrue(actual.isPresent());
         assertThat(actual.get(), instanceOf(ShorthandProjection.class));
         assertThat(((ShorthandProjection) actual.get()).getActualColumns().size(), is(6));
-        assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(crateExpectedColumnsWithOwner()));
+        assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(crateExpectedColumnsWithOwner(TypedSPILoader.getService(DatabaseType.class, "MySQL"))));
     }
     
     private JoinTableSegment createJoinTableSegmentWithUsingColumn() {
@@ -309,40 +312,42 @@ class ProjectionEngineTest {
     
     private Collection<Projection> crateExpectedColumnsWithoutOwnerForPostgreSQL() {
         Collection<Projection> result = new LinkedHashSet<>();
-        result.add(new ColumnProjection("o", "user_id", null));
-        result.add(new ColumnProjection("o", "order_id", null));
-        result.add(new ColumnProjection("o", "creation_date", null));
-        result.add(new ColumnProjection("o", "status", null));
-        result.add(new ColumnProjection("o", "merchant_id", null));
-        result.add(new ColumnProjection("o", "remark", null));
-        result.add(new ColumnProjection("i", "item_id", null));
-        result.add(new ColumnProjection("i", "product_id", null));
-        result.add(new ColumnProjection("i", "quantity", null));
+        DatabaseType postgresDatabaseType = TypedSPILoader.getService(DatabaseType.class, "PostgreSQL");
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("user_id", postgresDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("order_id", postgresDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("creation_date", postgresDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("status", postgresDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("merchant_id", postgresDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("remark", postgresDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("i"), new IdentifierValue("item_id", postgresDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("i"), new IdentifierValue("product_id", postgresDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("i"), new IdentifierValue("quantity", postgresDatabaseType.getQuoteCharacter()), null));
         return result;
     }
     
     private Collection<Projection> crateExpectedColumnsWithoutOwnerForMySQL() {
         Collection<Projection> result = new LinkedHashSet<>();
-        result.add(new ColumnProjection("i", "order_id", null));
-        result.add(new ColumnProjection("i", "user_id", null));
-        result.add(new ColumnProjection("i", "creation_date", null));
-        result.add(new ColumnProjection("i", "item_id", null));
-        result.add(new ColumnProjection("i", "product_id", null));
-        result.add(new ColumnProjection("i", "quantity", null));
-        result.add(new ColumnProjection("o", "status", null));
-        result.add(new ColumnProjection("o", "merchant_id", null));
-        result.add(new ColumnProjection("o", "remark", null));
+        DatabaseType mysqlDatabaseType = TypedSPILoader.getService(DatabaseType.class, "MySQL");
+        result.add(new ColumnProjection(new IdentifierValue("i"), new IdentifierValue("order_id", mysqlDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("i"), new IdentifierValue("user_id", mysqlDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("i"), new IdentifierValue("creation_date", mysqlDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("i"), new IdentifierValue("item_id", mysqlDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("i"), new IdentifierValue("product_id", mysqlDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("i"), new IdentifierValue("quantity", mysqlDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("status", mysqlDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("merchant_id", mysqlDatabaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("remark", mysqlDatabaseType.getQuoteCharacter()), null));
         return result;
     }
     
-    private Collection<Projection> crateExpectedColumnsWithOwner() {
+    private Collection<Projection> crateExpectedColumnsWithOwner(final DatabaseType databaseType) {
         Collection<Projection> result = new LinkedHashSet<>();
-        result.add(new ColumnProjection("o", "order_id", null));
-        result.add(new ColumnProjection("o", "user_id", null));
-        result.add(new ColumnProjection("o", "status", null));
-        result.add(new ColumnProjection("o", "merchant_id", null));
-        result.add(new ColumnProjection("o", "remark", null));
-        result.add(new ColumnProjection("o", "creation_date", null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("order_id", databaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("user_id", databaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("status", databaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("merchant_id", databaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("remark", databaseType.getQuoteCharacter()), null));
+        result.add(new ColumnProjection(new IdentifierValue("o"), new IdentifierValue("creation_date", databaseType.getQuoteCharacter()), null));
         return result;
     }
     
@@ -381,7 +386,7 @@ class ProjectionEngineTest {
         assertTrue(actual.isPresent());
         assertThat(actual.get(), instanceOf(ShorthandProjection.class));
         assertThat(((ShorthandProjection) actual.get()).getActualColumns().size(), is(6));
-        assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(crateExpectedColumnsWithOwner()));
+        assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(crateExpectedColumnsWithOwner(TypedSPILoader.getService(DatabaseType.class, "PostgreSQL"))));
     }
     
     @Test
@@ -394,7 +399,7 @@ class ProjectionEngineTest {
         assertTrue(actual.isPresent());
         assertThat(actual.get(), instanceOf(ShorthandProjection.class));
         assertThat(((ShorthandProjection) actual.get()).getActualColumns().size(), is(6));
-        assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(crateExpectedColumnsWithOwner()));
+        assertThat(((ShorthandProjection) actual.get()).getActualColumns(), is(crateExpectedColumnsWithOwner(TypedSPILoader.getService(DatabaseType.class, "MySQL"))));
     }
     
     private JoinTableSegment createJoinTableSegmentWithNaturalJoin() {
diff --git a/infra/rewrite/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameToken.java b/infra/rewrite/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameToken.java
index 33fdcdbef0a..be67b190489 100644
--- a/infra/rewrite/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameToken.java
+++ b/infra/rewrite/src/main/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameToken.java
@@ -128,9 +128,9 @@ public final class SubstitutableColumnNameToken extends SQLToken implements Subs
             QuoteCharacter ownerQuoteCharacter = tableAliasSegments.containsKey(owner.toLowerCase()) ? tableAliasSegments.get(owner.toLowerCase()).getIdentifier().getQuoteCharacter() : quoteCharacter;
             builder.append(ownerQuoteCharacter.wrap(logicActualTableNames.getOrDefault(owner, owner))).append('.');
         }
-        builder.append(quoteCharacter.wrap(columnProjection.getName()));
+        builder.append(columnProjection.getNameIdentifier().getQuoteCharacter().wrap(columnProjection.getName()));
         if (columnProjection.getAlias().isPresent()) {
-            builder.append(" AS ").append(quoteCharacter.wrap(columnProjection.getAlias().get()));
+            builder.append(" AS ").append(columnProjection.getAliasIdentifier().getQuoteCharacter().wrap(columnProjection.getAlias().get()));
         }
         return builder.toString();
     }
diff --git a/infra/rewrite/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameTokenTest.java b/infra/rewrite/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameTokenTest.java
index d09b5634f6d..806d2e738d5 100644
--- a/infra/rewrite/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameTokenTest.java
+++ b/infra/rewrite/src/test/java/org/apache/shardingsphere/infra/rewrite/sql/token/pojo/generic/SubstitutableColumnNameTokenTest.java
@@ -43,13 +43,15 @@ class SubstitutableColumnNameTokenTest {
     
     @Test
     void assertToStringWithQuote() {
-        Collection<ColumnProjection> projections = Collections.singletonList(new ColumnProjection(null, "id", "id"));
+        Collection<ColumnProjection> projections = Collections.singletonList(new ColumnProjection(null,
+                new IdentifierValue("id", QuoteCharacter.BACK_QUOTE), new IdentifierValue("id", QuoteCharacter.BACK_QUOTE)));
         assertThat(new SubstitutableColumnNameToken(0, 1, projections, QuoteCharacter.BACK_QUOTE, Collections.emptyList()).toString(mock(RouteUnit.class)), is("`id` AS `id`"));
     }
     
     @Test
     void assertToStringWithAliasQuote() {
-        Collection<ColumnProjection> projections = Collections.singletonList(new ColumnProjection("temp", "id", "id"));
+        Collection<ColumnProjection> projections = Collections.singletonList(new ColumnProjection(new IdentifierValue("temp", QuoteCharacter.BACK_QUOTE),
+                new IdentifierValue("id", QuoteCharacter.BACK_QUOTE), new IdentifierValue("id", QuoteCharacter.BACK_QUOTE)));
         SimpleTableSegment tableSegment = new SimpleTableSegment(new TableNameSegment(0, 0, new IdentifierValue("t_order")));
         tableSegment.setAlias(new AliasSegment(0, 0, new IdentifierValue("`temp`")));
         assertThat(new SubstitutableColumnNameToken(0, 1, projections, QuoteCharacter.BACK_QUOTE, Collections.singletonList(tableSegment)).toString(mock(RouteUnit.class)), is("`temp`.`id` AS `id`"));
diff --git a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/value/identifier/IdentifierValue.java b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/value/identifier/IdentifierValue.java
index b49c611ed96..65e6493b701 100644
--- a/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/value/identifier/IdentifierValue.java
+++ b/parser/sql/statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/value/identifier/IdentifierValue.java
@@ -18,6 +18,7 @@
 package org.apache.shardingsphere.sql.parser.sql.common.value.identifier;
 
 import com.google.common.base.Strings;
+import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
@@ -30,6 +31,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.value.ValueASTNode;
  */
 @RequiredArgsConstructor
 @Getter
+@EqualsAndHashCode
 @ToString
 public final class IdentifierValue implements ValueASTNode<String> {
     
diff --git a/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/select/select-subquery.xml b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/select/select-subquery.xml
index f2559faf53d..34cc55636b7 100644
--- a/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/select/select-subquery.xml
+++ b/test/it/rewriter/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/select/select-subquery.xml
@@ -94,7 +94,7 @@
 
     <rewrite-assertion id="select_not_nested_subquery_in_tablesegment_ref_shorthand" db-types="MySQL">
         <input sql="SELECT b.* FROM (SELECT a.certificate_number as certificate_number, a.amount FROM t_account a WHERE a.amount = 1373) b" />
-        <output sql="SELECT b.`cipher_certificate_number` AS `certificate_number`, b.`cipher_amount` AS `amount` FROM (SELECT a.cipher_certificate_number, a.assisted_query_certificate_number, a.cipher_amount FROM t_account a WHERE a.cipher_amount = 'encrypt_1373') b" />
+        <output sql="SELECT b.cipher_certificate_number AS certificate_number, b.cipher_amount AS amount FROM (SELECT a.cipher_certificate_number, a.assisted_query_certificate_number, a.cipher_amount FROM t_account a WHERE a.cipher_amount = 'encrypt_1373') b" />
     </rewrite-assertion>
 
     <rewrite-assertion id="select_with_exists_sub_query" db-types="MySQL">