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

menghaoran 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 6ba2391  Optimize EncryptProjectionTokenGenerator logic to improve 
performance (#15773)
6ba2391 is described below

commit 6ba23910f14269285cdfc82953de94b7c4ecb638
Author: Zhengqiang Duan <[email protected]>
AuthorDate: Thu Mar 3 17:42:40 2022 +0800

    Optimize EncryptProjectionTokenGenerator logic to improve performance 
(#15773)
    
    * Optimize EncryptProjectionTokenGenerator logic to improve performance
    
    * Fix unit test
---
 .../generator/EncryptProjectionTokenGenerator.java |  63 ++++++-------
 .../impl/EncryptProjectionTokenGeneratorTest.java  |   5 +-
 .../infra/binder/segment/table/TablesContext.java  | 100 ++++++++++++++-------
 3 files changed, 100 insertions(+), 68 deletions(-)

diff --git 
a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
 
b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
index dd8f21a..9f4c385 100644
--- 
a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
+++ 
b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptProjectionTokenGenerator.java
@@ -67,47 +67,46 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
     public Collection<SubstitutableColumnNameToken> generateSQLTokens(final 
SQLStatementContext<?> sqlStatementContext) {
         Preconditions.checkState(sqlStatementContext instanceof 
SelectStatementContext);
         Collection<SubstitutableColumnNameToken> result = new 
LinkedHashSet<>();
-        for (SelectStatementContext each : 
getSelectStatementContexts((SelectStatementContext) sqlStatementContext)) {
-            Map<String, String> columnTableNames = getColumnTableNames(each);
-            for (ProjectionSegment projection : 
each.getSqlStatement().getProjections().getProjections()) {
-                result.addAll(generateSQLTokens(each, projection, 
columnTableNames));
-            }
+        SelectStatementContext selectStatementContext = 
(SelectStatementContext) sqlStatementContext;
+        addGenerateSQLTokens(result, selectStatementContext);
+        for (SelectStatementContext each : 
selectStatementContext.getSubqueryContexts().values()) {
+            addGenerateSQLTokens(result, each);
         }
         return result;
     }
     
-    private Collection<SubstitutableColumnNameToken> generateSQLTokens(final 
SelectStatementContext selectStatementContext, 
-                                                                       final 
ProjectionSegment projection, final Map<String, String> columnTableNames) {
-        Collection<SubstitutableColumnNameToken> result = new LinkedList<>();
-        SubqueryType subqueryType = selectStatementContext.getSubqueryType();
-        if (projection instanceof ColumnProjectionSegment) {
-            ColumnProjectionSegment columnSegment = (ColumnProjectionSegment) 
projection;
-            ColumnProjection columnProjection = 
buildColumnProjection(columnSegment);
-            String tableName = 
columnTableNames.get(columnProjection.getExpression());
-            if (null != tableName && encryptRule.findEncryptor(tableName, 
columnProjection.getName()).isPresent()) {
-                result.add(generateSQLTokens(tableName, columnSegment, 
columnProjection, subqueryType));
+    private void addGenerateSQLTokens(final 
Collection<SubstitutableColumnNameToken> result, final SelectStatementContext 
selectStatementContext) {
+        Map<String, String> columnTableNames = 
getColumnTableNames(selectStatementContext);
+        for (ProjectionSegment projection : 
selectStatementContext.getSqlStatement().getProjections().getProjections()) {
+            SubqueryType subqueryType = 
selectStatementContext.getSubqueryType();
+            if (projection instanceof ColumnProjectionSegment) {
+                ColumnProjectionSegment columnSegment = 
(ColumnProjectionSegment) projection;
+                ColumnProjection columnProjection = 
buildColumnProjection(columnSegment);
+                String tableName = 
columnTableNames.get(columnProjection.getExpression());
+                if (null != tableName && 
encryptRule.findEncryptColumn(tableName, 
columnProjection.getName()).isPresent()) {
+                    result.add(generateSQLToken(tableName, columnSegment, 
columnProjection, subqueryType));
+                }
             }
-        }
-        if (projection instanceof ShorthandProjectionSegment) {
-            ShorthandProjectionSegment shorthandSegment = 
(ShorthandProjectionSegment) projection;
-            Collection<ColumnProjection> actualColumns = 
getShorthandProjection(shorthandSegment, 
selectStatementContext.getProjectionsContext()).getActualColumns().values();
-            if (!actualColumns.isEmpty()) {
-                result.add(generateSQLTokens(shorthandSegment, actualColumns, 
selectStatementContext.getDatabaseType(), subqueryType, columnTableNames));
+            if (projection instanceof ShorthandProjectionSegment) {
+                ShorthandProjectionSegment shorthandSegment = 
(ShorthandProjectionSegment) projection;
+                Collection<ColumnProjection> actualColumns = 
getShorthandProjection(shorthandSegment, 
selectStatementContext.getProjectionsContext()).getActualColumns().values();
+                if (!actualColumns.isEmpty()) {
+                    result.add(generateSQLToken(shorthandSegment, 
actualColumns, selectStatementContext.getDatabaseType(), subqueryType, 
columnTableNames));
+                }
             }
         }
-        return result;
     }
     
-    private SubstitutableColumnNameToken generateSQLTokens(final String 
tableName, final ColumnProjectionSegment columnSegment, 
-                                                           final 
ColumnProjection columnProjection, final SubqueryType subqueryType) {
+    private SubstitutableColumnNameToken generateSQLToken(final String 
tableName, final ColumnProjectionSegment columnSegment,
+                                                          final 
ColumnProjection columnProjection, final SubqueryType subqueryType) {
         Collection<ColumnProjection> projections = 
generateProjections(tableName, columnProjection, subqueryType, false, null);
         int startIndex = columnSegment.getColumn().getOwner().isPresent() ? 
columnSegment.getColumn().getOwner().get().getStopIndex() + 2 : 
columnSegment.getColumn().getStartIndex();
         int stopIndex = columnSegment.getStopIndex();
         return new SubstitutableColumnNameToken(startIndex, stopIndex, 
projections);
     }
     
-    private SubstitutableColumnNameToken generateSQLTokens(final 
ShorthandProjectionSegment segment, final Collection<ColumnProjection> 
actualColumns, 
-                                                           final DatabaseType 
databaseType, final SubqueryType subqueryType, final Map<String, String> 
columnTableNames) {
+    private SubstitutableColumnNameToken generateSQLToken(final 
ShorthandProjectionSegment segment, final Collection<ColumnProjection> 
actualColumns,
+                                                          final DatabaseType 
databaseType, final SubqueryType subqueryType, final Map<String, String> 
columnTableNames) {
         List<ColumnProjection> projections = new LinkedList<>();
         for (ColumnProjection each : actualColumns) {
             String tableName = columnTableNames.get(each.getExpression());
@@ -140,13 +139,6 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
         return 
selectStatementContext.getTablesContext().findTableNamesByColumnProjection(columns,
 schema);
     }
     
-    private Collection<SelectStatementContext> 
getSelectStatementContexts(final SelectStatementContext selectStatementContext) 
{
-        Collection<SelectStatementContext> result = new LinkedList<>();
-        result.add(selectStatementContext);
-        result.addAll(selectStatementContext.getSubqueryContexts().values());
-        return result;
-    }
-    
     private Collection<ColumnProjection> generateProjections(final String 
tableName, final ColumnProjection column, final SubqueryType subqueryType, 
final boolean shorthand, 
                                                              final 
ShorthandProjectionSegment segment) {
         Collection<ColumnProjection> result = new LinkedList<>();
@@ -203,15 +195,14 @@ public final class EncryptProjectionTokenGenerator 
implements CollectionSQLToken
     
     private ColumnProjection generateCommonProjection(final String tableName, 
final ColumnProjection column, final ShorthandProjectionSegment segment) {
         String encryptColumnName = getEncryptColumnName(tableName, 
column.getName());
-        String owner = (segment != null && segment.getOwner().isPresent()) ? 
segment.getOwner().get().getIdentifier().getValue() : column.getOwner();
+        String owner = (null != segment && segment.getOwner().isPresent()) ? 
segment.getOwner().get().getIdentifier().getValue() : column.getOwner();
         return new ColumnProjection(owner, encryptColumnName, 
column.getAlias().orElse(column.getName()));
     }
     
     private String getEncryptColumnName(final String tableName, final String 
logicEncryptColumnName) {
-        Optional<String> plainColumn = encryptRule.findPlainColumn(tableName, 
logicEncryptColumnName);
         boolean queryWithCipherColumn = 
encryptRule.isQueryWithCipherColumn(tableName);
         if (!queryWithCipherColumn) {
-            return plainColumn.orElseGet(() -> 
encryptRule.getCipherColumn(tableName, logicEncryptColumnName));
+            return encryptRule.findPlainColumn(tableName, 
logicEncryptColumnName).orElseGet(() -> encryptRule.getCipherColumn(tableName, 
logicEncryptColumnName));
         }
         return encryptRule.getCipherColumn(tableName, logicEncryptColumnName);
     }
diff --git 
a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/impl/EncryptProjectionTokenGeneratorTest.java
 
b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/impl/EncryptProjectionTokenGeneratorTest.java
index 78646ce..d18439c 100644
--- 
a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/impl/EncryptProjectionTokenGeneratorTest.java
+++ 
b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/impl/EncryptProjectionTokenGeneratorTest.java
@@ -17,8 +17,8 @@
 
 package org.apache.shardingsphere.encrypt.rewrite.impl;
 
-import org.apache.shardingsphere.encrypt.fixture.TestEncryptAlgorithm;
 import 
org.apache.shardingsphere.encrypt.rewrite.token.generator.EncryptProjectionTokenGenerator;
+import org.apache.shardingsphere.encrypt.rule.EncryptColumn;
 import org.apache.shardingsphere.encrypt.rule.EncryptRule;
 import org.apache.shardingsphere.encrypt.rule.EncryptTable;
 import 
org.apache.shardingsphere.infra.binder.segment.select.projection.impl.ColumnProjection;
@@ -120,7 +120,8 @@ public final class EncryptProjectionTokenGeneratorTest {
         when(encryptRule.findPlainColumn("doctor1", 
"mobile")).thenReturn(Optional.of("Mobile"));
         
when(encryptRule.findEncryptTable("doctor")).thenReturn(Optional.of(encryptTable1));
         
when(encryptRule.findEncryptTable("doctor1")).thenReturn(Optional.of(encryptTable2));
-        when(encryptRule.findEncryptor("doctor", 
"mobile")).thenReturn(Optional.of(new TestEncryptAlgorithm()));
+        EncryptColumn column = new EncryptColumn(null, "mobile", null, null, 
null, "mobile", null, null);
+        when(encryptRule.findEncryptColumn("doctor", 
"mobile")).thenReturn(Optional.of(column));
         return encryptRule;
     }
 }
diff --git 
a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/table/TablesContext.java
 
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/table/TablesContext.java
index 26615ed..3e32652 100644
--- 
a/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/table/TablesContext.java
+++ 
b/shardingsphere-infra/shardingsphere-infra-binder/src/main/java/org/apache/shardingsphere/infra/binder/segment/table/TablesContext.java
@@ -26,11 +26,9 @@ import 
org.apache.shardingsphere.infra.binder.segment.select.subquery.engine.Sub
 import 
org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.metadata.schema.ShardingSphereSchema;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
-import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.OwnerSegment;
 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.value.identifier.IdentifierValue;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -113,12 +111,14 @@ public final class TablesContext {
      */
     public Map<String, String> findTableNamesByColumnSegment(final 
Collection<ColumnSegment> columns, final ShardingSphereSchema schema) {
         if (1 == tables.size()) {
-            return findTableNameFromSingleTable(columns);
+            return findTableNameFromSingleTableByColumnSegment(columns);
         }
         Map<String, String> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
-        result.putAll(findTableNameFromSQL(columns));
-        result.putAll(findTableNameFromMetaData(columns, schema));
-        result.putAll(findTableNameFromSubquery(columns, result));
+        Map<String, Collection<String>> ownerColumnNames = 
getOwnerColumnNamesByColumnSegment(columns);
+        result.putAll(findTableNameFromSQL(ownerColumnNames));
+        Collection<String> noOwnerColumnNames = 
getNoOwnerColumnNamesByColumnSegment(columns);
+        result.putAll(findTableNameFromMetaData(noOwnerColumnNames, schema));
+        result.putAll(findTableNameFromSubqueryByColumnSegment(columns, 
result));
         return result;
     }
     
@@ -130,26 +130,19 @@ public final class TablesContext {
      * @return expression table name map
      */
     public Map<String, String> findTableNamesByColumnProjection(final 
Collection<ColumnProjection> columns, final ShardingSphereSchema schema) {
-        Collection<ColumnSegment> result = new LinkedList<>();
-        for (ColumnProjection each : columns) {
-            ColumnSegment columnSegment = new ColumnSegment(0, 0, new 
IdentifierValue(each.getName()));
-            if (null != each.getOwner()) {
-                columnSegment.setOwner(new OwnerSegment(0, 0, new 
IdentifierValue(each.getOwner())));
-            }
-            result.add(columnSegment);
-        }
-        return findTableNamesByColumnSegment(result, schema);
-    }
-    
-    private ColumnSegment createColumnSegment(final ColumnProjection 
projection) {
-        ColumnSegment result = new ColumnSegment(0, 0, new 
IdentifierValue(projection.getName()));
-        if (null != projection.getOwner()) {
-            result.setOwner(new OwnerSegment(0, 0, new 
IdentifierValue(projection.getOwner())));
+        if (1 == tables.size()) {
+            return findTableNameFromSingleTableByColumnProjection(columns);
         }
+        Map<String, String> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        Map<String, Collection<String>> ownerColumnNames = 
getOwnerColumnNamesByColumnProjection(columns);
+        result.putAll(findTableNameFromSQL(ownerColumnNames));
+        Collection<String> noOwnerColumnNames = 
getNoOwnerColumnNamesByColumnProjection(columns);
+        result.putAll(findTableNameFromMetaData(noOwnerColumnNames, schema));
+        result.putAll(findTableNameFromSubqueryByColumnProjection(columns, 
result));
         return result;
     }
     
-    private Map<String, String> findTableNameFromSubquery(final 
Collection<ColumnSegment> columns, final Map<String, String> ownerTableNames) {
+    private Map<String, String> findTableNameFromSubqueryByColumnSegment(final 
Collection<ColumnSegment> columns, final Map<String, String> ownerTableNames) {
         if (ownerTableNames.size() == columns.size() || 
subqueryTables.isEmpty()) {
             return Collections.emptyMap();
         }
@@ -169,7 +162,26 @@ public final class TablesContext {
         return result;
     }
     
-    private Map<String, String> findTableNameFromSingleTable(final 
Collection<ColumnSegment> columns) {
+    private Map<String, String> 
findTableNameFromSubqueryByColumnProjection(final Collection<ColumnProjection> 
columns, final Map<String, String> ownerTableNames) {
+        if (ownerTableNames.size() == columns.size() || 
subqueryTables.isEmpty()) {
+            return Collections.emptyMap();
+        }
+        Map<String, String> result = new LinkedHashMap<>(columns.size(), 1);
+        for (ColumnProjection each : columns) {
+            if (ownerTableNames.containsKey(each.getExpression())) {
+                continue;
+            }
+            Collection<SubqueryTableContext> subqueryTableContexts = 
subqueryTables.getOrDefault(each.getOwner(), Collections.emptyList());
+            for (SubqueryTableContext subqueryTableContext : 
subqueryTableContexts) {
+                if 
(subqueryTableContext.getColumnNames().contains(each.getName())) {
+                    result.put(each.getExpression(), 
subqueryTableContext.getTableName());
+                }
+            }
+        }
+        return result;
+    }
+    
+    private Map<String, String> 
findTableNameFromSingleTableByColumnSegment(final Collection<ColumnSegment> 
columns) {
         String tableName = 
tables.iterator().next().getTableName().getIdentifier().getValue();
         Map<String, String> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
         for (ColumnSegment each : columns) {
@@ -178,7 +190,16 @@ public final class TablesContext {
         return result;
     }
     
-    private Map<String, Collection<String>> getOwnerColumnNames(final 
Collection<ColumnSegment> columns) {
+    private Map<String, String> 
findTableNameFromSingleTableByColumnProjection(final 
Collection<ColumnProjection> columns) {
+        String tableName = 
tables.iterator().next().getTableName().getIdentifier().getValue();
+        Map<String, String> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        for (ColumnProjection each : columns) {
+            result.putIfAbsent(each.getExpression(), tableName);
+        }
+        return result;
+    }
+    
+    private Map<String, Collection<String>> 
getOwnerColumnNamesByColumnSegment(final Collection<ColumnSegment> columns) {
         Map<String, Collection<String>> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
         for (ColumnSegment each : columns) {
             if (!each.getOwner().isPresent()) {
@@ -189,12 +210,22 @@ public final class TablesContext {
         return result;
     }
     
-    private Map<String, String> findTableNameFromSQL(final 
Collection<ColumnSegment> columns) {
-        Map<String, Collection<String>> ownerColumnNames = 
getOwnerColumnNames(columns);
+    private Map<String, Collection<String>> 
getOwnerColumnNamesByColumnProjection(final Collection<ColumnProjection> 
columns) {
+        Map<String, Collection<String>> result = new 
TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+        for (ColumnProjection each : columns) {
+            if (null == each.getOwner()) {
+                continue;
+            }
+            result.computeIfAbsent(each.getOwner(), unused -> new 
LinkedList<>()).add(each.getExpression());
+        }
+        return result;
+    }
+    
+    private Map<String, String> findTableNameFromSQL(final Map<String, 
Collection<String>> ownerColumnNames) {
         if (ownerColumnNames.isEmpty()) {
             return Collections.emptyMap();
         }
-        Map<String, String> result = new LinkedHashMap<>(columns.size(), 1);
+        Map<String, String> result = new LinkedHashMap<>();
         for (SimpleTableSegment each : tables) {
             String tableName = each.getTableName().getIdentifier().getValue();
             if (ownerColumnNames.containsKey(tableName)) {
@@ -208,8 +239,7 @@ public final class TablesContext {
         return result;
     }
     
-    private Map<String, String> findTableNameFromMetaData(final 
Collection<ColumnSegment> columns, final ShardingSphereSchema schema) {
-        Collection<String> noOwnerColumnNames = getNoOwnerColumnNames(columns);
+    private Map<String, String> findTableNameFromMetaData(final 
Collection<String> noOwnerColumnNames, final ShardingSphereSchema schema) {
         if (noOwnerColumnNames.isEmpty()) {
             return Collections.emptyMap();
         }
@@ -225,7 +255,7 @@ public final class TablesContext {
         return result;
     }
     
-    private Collection<String> getNoOwnerColumnNames(final 
Collection<ColumnSegment> columns) {
+    private Collection<String> getNoOwnerColumnNamesByColumnSegment(final 
Collection<ColumnSegment> columns) {
         Collection<String> result = new 
TreeSet<>(String.CASE_INSENSITIVE_ORDER);
         for (ColumnSegment each : columns) {
             if (!each.getOwner().isPresent()) {
@@ -235,6 +265,16 @@ public final class TablesContext {
         return result;
     }
     
+    private Collection<String> getNoOwnerColumnNamesByColumnProjection(final 
Collection<ColumnProjection> columns) {
+        Collection<String> result = new 
TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+        for (ColumnProjection each : columns) {
+            if (null == each.getOwner()) {
+                result.add(each.getName());
+            }
+        }
+        return result;
+    }
+    
     /**
      * Get schema name.
      *

Reply via email to