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/03/20 03:54:39 UTC

[shardingsphere] branch master updated: Add ColumnContainedRule for EncryptRule and MaskRule (#24679)

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 ed9a1739ac5 Add ColumnContainedRule for EncryptRule and MaskRule (#24679)
ed9a1739ac5 is described below

commit ed9a1739ac5ddd38c3dc04913a945dbf61091320
Author: zhaojinchao <zh...@apache.org>
AuthorDate: Mon Mar 20 11:54:32 2023 +0800

    Add ColumnContainedRule for EncryptRule and MaskRule (#24679)
    
    * Add ColumnContainedRule for EncryptRule and MaskRule
    
    * Fix checkstyle
---
 .../shardingsphere/encrypt/rule/EncryptRule.java   |  3 +-
 .../apache/shardingsphere/mask/rule/MaskRule.java  |  3 +-
 .../rule/identifier/type/ColumnContainedRule.java  | 35 +++++++++++++++++++++
 .../resultset/ShardingSphereResultSetMetaData.java | 25 +++++++++++++++
 .../driver/jdbc/adapter/ResultSetAdapterTest.java  | 14 ++++++++-
 .../proxy/backend/connector/DatabaseConnector.java | 36 +++++++++++++++++-----
 6 files changed, 106 insertions(+), 10 deletions(-)

diff --git a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptRule.java b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptRule.java
index b5acaa93327..1bd431d2f59 100644
--- a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptRule.java
+++ b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rule/EncryptRule.java
@@ -29,6 +29,7 @@ import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
 import org.apache.shardingsphere.encrypt.spi.context.EncryptContext;
 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
 import org.apache.shardingsphere.infra.rule.identifier.scope.DatabaseRule;
+import org.apache.shardingsphere.infra.rule.identifier.type.ColumnContainedRule;
 import org.apache.shardingsphere.infra.rule.identifier.type.TableContainedRule;
 import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
 import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPILoader;
@@ -44,7 +45,7 @@ import java.util.Optional;
 /**
  * Encrypt rule.
  */
-public final class EncryptRule implements DatabaseRule, TableContainedRule {
+public final class EncryptRule implements DatabaseRule, TableContainedRule, ColumnContainedRule {
     
     @Getter
     private final RuleConfiguration configuration;
diff --git a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/rule/MaskRule.java b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/rule/MaskRule.java
index 139b2489a8f..13e2a2bd380 100644
--- a/features/mask/core/src/main/java/org/apache/shardingsphere/mask/rule/MaskRule.java
+++ b/features/mask/core/src/main/java/org/apache/shardingsphere/mask/rule/MaskRule.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.mask.rule;
 import lombok.Getter;
 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
 import org.apache.shardingsphere.infra.rule.identifier.scope.DatabaseRule;
+import org.apache.shardingsphere.infra.rule.identifier.type.ColumnContainedRule;
 import org.apache.shardingsphere.infra.rule.identifier.type.TableContainedRule;
 import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.mask.api.config.MaskRuleConfiguration;
@@ -34,7 +35,7 @@ import java.util.Optional;
  * Mask rule.
  */
 @SuppressWarnings("rawtypes")
-public final class MaskRule implements DatabaseRule, TableContainedRule {
+public final class MaskRule implements DatabaseRule, TableContainedRule, ColumnContainedRule {
     
     @Getter
     private final RuleConfiguration configuration;
diff --git a/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/identifier/type/ColumnContainedRule.java b/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/identifier/type/ColumnContainedRule.java
new file mode 100644
index 00000000000..cd15c9f768b
--- /dev/null
+++ b/infra/common/src/main/java/org/apache/shardingsphere/infra/rule/identifier/type/ColumnContainedRule.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.infra.rule.identifier.type;
+
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+
+import java.util.Collection;
+
+/**
+ * ShardingSphere rule which contains column.
+ */
+public interface ColumnContainedRule extends ShardingSphereRule {
+    
+    /**
+     * Get tables.
+     *
+     * @return tables
+     */
+    Collection<String> getTables();
+}
diff --git a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/resultset/ShardingSphereResultSetMetaData.java b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/resultset/ShardingSphereResultSetMetaData.java
index bcd810d0df2..87b8f90dadc 100644
--- a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/resultset/ShardingSphereResultSetMetaData.java
+++ b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/resultset/ShardingSphereResultSetMetaData.java
@@ -28,7 +28,9 @@ import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.database.DefaultDatabase;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
+import org.apache.shardingsphere.infra.rule.identifier.type.ColumnContainedRule;
 import org.apache.shardingsphere.infra.rule.identifier.type.DataNodeContainedRule;
+import org.apache.shardingsphere.infra.rule.identifier.type.MutableDataNodeRule;
 
 import java.sql.ResultSetMetaData;
 import java.sql.SQLException;
@@ -50,6 +52,9 @@ public final class ShardingSphereResultSetMetaData extends WrapperAdapter implem
     @Override
     public int getColumnCount() throws SQLException {
         if (sqlStatementContext instanceof SelectStatementContext) {
+            if (isAllSingleTable()) {
+                return resultSetMetaData.getColumnCount();
+            }
             if (hasSelectExpandProjections()) {
                 return ((SelectStatementContext) sqlStatementContext).getProjectionsContext().getExpandProjections().size();
             }
@@ -95,6 +100,9 @@ public final class ShardingSphereResultSetMetaData extends WrapperAdapter implem
     
     @Override
     public String getColumnLabel(final int column) throws SQLException {
+        if (isAllSingleTable()) {
+            return resultSetMetaData.getColumnLabel(column);
+        }
         if (hasSelectExpandProjections()) {
             checkColumnIndex(column);
             Projection projection = ((SelectStatementContext) sqlStatementContext).getProjectionsContext().getExpandProjections().get(column - 1);
@@ -107,6 +115,9 @@ public final class ShardingSphereResultSetMetaData extends WrapperAdapter implem
     
     @Override
     public String getColumnName(final int column) throws SQLException {
+        if (isAllSingleTable()) {
+            return resultSetMetaData.getColumnName(column);
+        }
         if (hasSelectExpandProjections()) {
             checkColumnIndex(column);
             Projection projection = ((SelectStatementContext) sqlStatementContext).getProjectionsContext().getExpandProjections().get(column - 1);
@@ -124,6 +135,20 @@ public final class ShardingSphereResultSetMetaData extends WrapperAdapter implem
         return sqlStatementContext instanceof SelectStatementContext && !((SelectStatementContext) sqlStatementContext).getProjectionsContext().getExpandProjections().isEmpty();
     }
     
+    private boolean isAllSingleTable() {
+        return sqlStatementContext.getTablesContext().getTableNames().stream().allMatch(each -> !containsInImmutableDataNodeContainedRule(each)
+                && !containsInColumnContainedRule(each));
+    }
+    
+    private boolean containsInImmutableDataNodeContainedRule(final String tableName) {
+        return database.getRuleMetaData().findRules(DataNodeContainedRule.class).stream()
+                .filter(each -> !(each instanceof MutableDataNodeRule)).anyMatch(each -> each.getAllTables().contains(tableName));
+    }
+    
+    private boolean containsInColumnContainedRule(final String tableName) {
+        return database.getRuleMetaData().findRules(ColumnContainedRule.class).stream().anyMatch(each -> each.getTables().contains(tableName));
+    }
+    
     private void checkColumnIndex(final int column) throws SQLException {
         List<Projection> actualProjections = ((SelectStatementContext) sqlStatementContext).getProjectionsContext().getExpandProjections();
         if (column > actualProjections.size()) {
diff --git a/jdbc/core/src/test/java/org/apache/shardingsphere/driver/jdbc/adapter/ResultSetAdapterTest.java b/jdbc/core/src/test/java/org/apache/shardingsphere/driver/jdbc/adapter/ResultSetAdapterTest.java
index 618d54c58b1..d131f855397 100644
--- a/jdbc/core/src/test/java/org/apache/shardingsphere/driver/jdbc/adapter/ResultSetAdapterTest.java
+++ b/jdbc/core/src/test/java/org/apache/shardingsphere/driver/jdbc/adapter/ResultSetAdapterTest.java
@@ -19,6 +19,8 @@ package org.apache.shardingsphere.driver.jdbc.adapter;
 
 import org.apache.shardingsphere.driver.jdbc.core.resultset.ShardingSphereResultSet;
 import org.apache.shardingsphere.driver.jdbc.core.statement.ShardingSphereStatement;
+import org.apache.shardingsphere.infra.binder.segment.table.TablesContext;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
 import org.apache.shardingsphere.infra.merge.result.MergedResult;
 import org.junit.jupiter.api.Test;
@@ -111,6 +113,16 @@ public final class ResultSetAdapterTest {
         when(resultSetMetaData.getColumnLabel(1)).thenReturn("col");
         when(resultSetMetaData.getColumnCount()).thenReturn(1);
         when(resultSet.getMetaData()).thenReturn(resultSetMetaData);
-        return new ShardingSphereResultSet(Collections.singletonList(resultSet), mock(MergedResult.class), mock(ShardingSphereStatement.class, RETURNS_DEEP_STUBS), mock(ExecutionContext.class));
+        return new ShardingSphereResultSet(Collections.singletonList(resultSet), mock(MergedResult.class), mock(ShardingSphereStatement.class, RETURNS_DEEP_STUBS), createExecutionContext());
+    }
+    
+    private ExecutionContext createExecutionContext() {
+        ExecutionContext result = mock(ExecutionContext.class);
+        SQLStatementContext sqlStatementContext = mock(SQLStatementContext.class);
+        TablesContext tablesContext = mock(TablesContext.class);
+        when(tablesContext.getTableNames()).thenReturn(Collections.emptyList());
+        when(sqlStatementContext.getTablesContext()).thenReturn(tablesContext);
+        when(result.getSqlStatementContext()).thenReturn(sqlStatementContext);
+        return result;
     }
 }
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
index b581068c0b1..a261fac31aa 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
@@ -49,7 +49,9 @@ import org.apache.shardingsphere.infra.merge.MergeEngine;
 import org.apache.shardingsphere.infra.merge.result.MergedResult;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.schema.util.SystemSchemaUtil;
+import org.apache.shardingsphere.infra.rule.identifier.type.ColumnContainedRule;
 import org.apache.shardingsphere.infra.rule.identifier.type.DataNodeContainedRule;
+import org.apache.shardingsphere.infra.rule.identifier.type.MutableDataNodeRule;
 import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
@@ -324,23 +326,43 @@ public final class DatabaseConnector implements DatabaseBackendHandler {
         return result;
     }
     
-    private QueryHeader createQueryHeader(final QueryHeaderBuilderEngine queryHeaderBuilderEngine, final ExecutionContext executionContext,
-                                          final QueryResult queryResultSample, final ShardingSphereDatabase database, final int columnIndex) throws SQLException {
-        return hasSelectExpandProjections(executionContext.getSqlStatementContext()) ? queryHeaderBuilderEngine.build(
-                ((SelectStatementContext) executionContext.getSqlStatementContext()).getProjectionsContext(), queryResultSample.getMetaData(), database, columnIndex)
-                : queryHeaderBuilderEngine.build(queryResultSample.getMetaData(), database, columnIndex);
-    }
-    
     private int getColumnCount(final ExecutionContext executionContext, final QueryResult queryResultSample) throws SQLException {
+        if (isAllSingleTable(executionContext.getSqlStatementContext())) {
+            return queryResultSample.getMetaData().getColumnCount();
+        }
         return hasSelectExpandProjections(executionContext.getSqlStatementContext())
                 ? ((SelectStatementContext) executionContext.getSqlStatementContext()).getProjectionsContext().getExpandProjections().size()
                 : queryResultSample.getMetaData().getColumnCount();
     }
     
+    private boolean isAllSingleTable(final SQLStatementContext<?> sqlStatementContext) {
+        return sqlStatementContext.getTablesContext().getTableNames().stream().allMatch(each -> !containsInImmutableDataNodeContainedRule(each)
+                && !containsInColumnContainedRule(each));
+    }
+    
+    private boolean containsInImmutableDataNodeContainedRule(final String tableName) {
+        return database.getRuleMetaData().findRules(DataNodeContainedRule.class).stream()
+                .filter(each -> !(each instanceof MutableDataNodeRule)).anyMatch(each -> each.getAllTables().contains(tableName));
+    }
+    
+    private boolean containsInColumnContainedRule(final String tableName) {
+        return database.getRuleMetaData().findRules(ColumnContainedRule.class).stream().anyMatch(each -> each.getTables().contains(tableName));
+    }
+    
     private boolean hasSelectExpandProjections(final SQLStatementContext<?> sqlStatementContext) {
         return sqlStatementContext instanceof SelectStatementContext && !((SelectStatementContext) sqlStatementContext).getProjectionsContext().getExpandProjections().isEmpty();
     }
     
+    private QueryHeader createQueryHeader(final QueryHeaderBuilderEngine queryHeaderBuilderEngine, final ExecutionContext executionContext,
+                                          final QueryResult queryResultSample, final ShardingSphereDatabase database, final int columnIndex) throws SQLException {
+        if (isAllSingleTable(executionContext.getSqlStatementContext())) {
+            return queryHeaderBuilderEngine.build(queryResultSample.getMetaData(), database, columnIndex);
+        }
+        return hasSelectExpandProjections(executionContext.getSqlStatementContext())
+                ? queryHeaderBuilderEngine.build(((SelectStatementContext) executionContext.getSqlStatementContext()).getProjectionsContext(), queryResultSample.getMetaData(), database, columnIndex)
+                : queryHeaderBuilderEngine.build(queryResultSample.getMetaData(), database, columnIndex);
+    }
+    
     private MergedResult mergeQuery(final SQLStatementContext<?> sqlStatementContext, final List<QueryResult> queryResults) throws SQLException {
         MergeEngine mergeEngine = new MergeEngine(database, ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getProps(),
                 backendConnection.getConnectionSession().getConnectionContext());