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.
*