You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2022/07/26 03:21:55 UTC

[shardingsphere] branch master updated: Support encrypt column rewrite when execute column is null in predicate (#19543)

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

zhaojinchao 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 7a1d8ce8d2e Support encrypt column rewrite when execute column is null in predicate (#19543)
7a1d8ce8d2e is described below

commit 7a1d8ce8d2e893dd3ff52490ecb6d366eba7a4cf
Author: Zhengqiang Duan <du...@apache.org>
AuthorDate: Tue Jul 26 11:21:46 2022 +0800

    Support encrypt column rewrite when execute column is null in predicate (#19543)
---
 .../rewrite/condition/EncryptConditionEngine.java  | 21 ++++++++++++++++-
 .../generator/EncryptAssignmentTokenGenerator.java |  6 ++---
 .../EncryptInsertValuesTokenGenerator.java         |  2 +-
 .../EncryptOrderByItemTokenGenerator.java          |  8 +++----
 .../generator/InsertCipherNameTokenGenerator.java  |  2 +-
 .../sql/common/util/ExpressionExtractUtil.java     | 27 +---------------------
 .../case/query-with-cipher/dml/update/update.xml   |  8 +++----
 7 files changed, 33 insertions(+), 41 deletions(-)

diff --git a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java
index f7ede9ab31d..3047c2d99b8 100644
--- a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java
+++ b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/condition/EncryptConditionEngine.java
@@ -31,6 +31,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.BetweenE
 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.expr.InExpression;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.SimpleExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.subquery.SubqueryExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
@@ -110,7 +111,7 @@ public final class EncryptConditionEngine {
     }
     
     private void addEncryptConditions(final Collection<EncryptCondition> encryptConditions, final ExpressionSegment expression, final Map<String, String> expressionTableNames) {
-        if (!ExpressionExtractUtil.findNotContainsNullLiteralsExpression(expression).isPresent()) {
+        if (!findNotContainsNullLiteralsExpression(expression).isPresent()) {
             return;
         }
         for (ColumnSegment each : ColumnExtractor.extract(expression)) {
@@ -121,6 +122,24 @@ public final class EncryptConditionEngine {
         }
     }
     
+    private Optional<ExpressionSegment> findNotContainsNullLiteralsExpression(final ExpressionSegment expression) {
+        if (isContainsNullLiterals(expression)) {
+            return Optional.empty();
+        }
+        if (expression instanceof BinaryOperationExpression && isContainsNullLiterals(((BinaryOperationExpression) expression).getRight())) {
+            return Optional.empty();
+        }
+        return Optional.ofNullable(expression);
+    }
+    
+    private boolean isContainsNullLiterals(final ExpressionSegment expression) {
+        if (!(expression instanceof LiteralExpressionSegment)) {
+            return false;
+        }
+        String literals = String.valueOf(((LiteralExpressionSegment) expression).getLiterals());
+        return "NULL".equalsIgnoreCase(literals) || "NOT NULL".equalsIgnoreCase(literals);
+    }
+    
     private Optional<EncryptCondition> createEncryptCondition(final ExpressionSegment expression, final String tableName) {
         if (expression instanceof BinaryOperationExpression) {
             return createBinaryEncryptCondition((BinaryOperationExpression) expression, tableName);
diff --git a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptAssignmentTokenGenerator.java b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptAssignmentTokenGenerator.java
index 3b974ab477e..e61bcf167df 100644
--- a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptAssignmentTokenGenerator.java
+++ b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptAssignmentTokenGenerator.java
@@ -49,20 +49,20 @@ import java.util.Optional;
  * Assignment generator for encrypt.
  */
 @Setter
-public final class EncryptAssignmentTokenGenerator implements CollectionSQLTokenGenerator, EncryptRuleAware, DatabaseNameAware {
+public final class EncryptAssignmentTokenGenerator implements CollectionSQLTokenGenerator<SQLStatementContext<?>>, EncryptRuleAware, DatabaseNameAware {
     
     private EncryptRule encryptRule;
     
     private String databaseName;
     
     @Override
-    public boolean isGenerateSQLToken(final SQLStatementContext sqlStatementContext) {
+    public boolean isGenerateSQLToken(final SQLStatementContext<?> sqlStatementContext) {
         return sqlStatementContext instanceof UpdateStatementContext || (sqlStatementContext instanceof InsertStatementContext
                 && InsertStatementHandler.getSetAssignmentSegment(((InsertStatementContext) sqlStatementContext).getSqlStatement()).isPresent());
     }
     
     @Override
-    public Collection<EncryptAssignmentToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
+    public Collection<EncryptAssignmentToken> generateSQLTokens(final SQLStatementContext<?> sqlStatementContext) {
         Collection<EncryptAssignmentToken> result = new LinkedList<>();
         String tableName = ((TableAvailable) sqlStatementContext).getAllTables().iterator().next().getTableName().getIdentifier().getValue();
         String schemaName = sqlStatementContext.getTablesContext().getSchemaName().orElseGet(() -> DatabaseTypeEngine.getDefaultSchemaName(sqlStatementContext.getDatabaseType(), databaseName));
diff --git a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptInsertValuesTokenGenerator.java b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptInsertValuesTokenGenerator.java
index 24a6f37bdda..1add58f9048 100644
--- a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptInsertValuesTokenGenerator.java
+++ b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptInsertValuesTokenGenerator.java
@@ -62,7 +62,7 @@ public final class EncryptInsertValuesTokenGenerator implements OptionalSQLToken
     private String databaseName;
     
     @Override
-    public boolean isGenerateSQLToken(final SQLStatementContext sqlStatementContext) {
+    public boolean isGenerateSQLToken(final SQLStatementContext<?> sqlStatementContext) {
         return sqlStatementContext instanceof InsertStatementContext && !(((InsertStatementContext) sqlStatementContext).getSqlStatement()).getValues().isEmpty();
     }
     
diff --git a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java
index be125265ba9..c21a0330f29 100644
--- a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java
+++ b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/EncryptOrderByItemTokenGenerator.java
@@ -44,7 +44,7 @@ import java.util.Optional;
  * Order by item token generator for encrypt.
  */
 @Setter
-public final class EncryptOrderByItemTokenGenerator implements CollectionSQLTokenGenerator, SchemaMetaDataAware, EncryptRuleAware {
+public final class EncryptOrderByItemTokenGenerator implements CollectionSQLTokenGenerator<SQLStatementContext<?>>, SchemaMetaDataAware, EncryptRuleAware {
     
     private String databaseName;
     
@@ -52,15 +52,13 @@ public final class EncryptOrderByItemTokenGenerator implements CollectionSQLToke
     
     private EncryptRule encryptRule;
     
-    @SuppressWarnings("rawtypes")
     @Override
-    public boolean isGenerateSQLToken(final SQLStatementContext sqlStatementContext) {
+    public boolean isGenerateSQLToken(final SQLStatementContext<?> sqlStatementContext) {
         return sqlStatementContext instanceof SelectStatementContext && containsOrderByItem(sqlStatementContext);
     }
     
-    @SuppressWarnings("rawtypes")
     @Override
-    public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext sqlStatementContext) {
+    public Collection<SubstitutableColumnNameToken> generateSQLTokens(final SQLStatementContext<?> sqlStatementContext) {
         Collection<SubstitutableColumnNameToken> result = new LinkedHashSet<>();
         String defaultSchema = DatabaseTypeEngine.getDefaultSchemaName(sqlStatementContext.getDatabaseType(), databaseName);
         ShardingSphereSchema schema = sqlStatementContext.getTablesContext().getSchemaName().map(schemas::get).orElseGet(() -> schemas.get(defaultSchema));
diff --git a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/InsertCipherNameTokenGenerator.java b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/InsertCipherNameTokenGenerator.java
index ffc36f5d2ae..586a616fdf0 100644
--- a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/InsertCipherNameTokenGenerator.java
+++ b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/InsertCipherNameTokenGenerator.java
@@ -44,7 +44,7 @@ public final class InsertCipherNameTokenGenerator implements CollectionSQLTokenG
     private EncryptRule encryptRule;
     
     @Override
-    public boolean isGenerateSQLToken(final SQLStatementContext sqlStatementContext) {
+    public boolean isGenerateSQLToken(final SQLStatementContext<?> sqlStatementContext) {
         if (!(sqlStatementContext instanceof InsertStatementContext)) {
             return false;
         }
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtil.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtil.java
index fb48d46e18a..16630d75371 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtil.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/ExpressionExtractUtil.java
@@ -23,7 +23,6 @@ import org.apache.shardingsphere.sql.parser.sql.common.constant.LogicalOperator;
 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.expr.FunctionSegment;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.LiteralExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.simple.ParameterMarkerExpressionSegment;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
 
@@ -83,34 +82,10 @@ public final class ExpressionExtractUtil {
     
     private static AndPredicate createAndPredicate(final ExpressionSegment expression) {
         AndPredicate result = new AndPredicate();
-        findNotContainsNullLiteralsExpression(expression).ifPresent(optional -> result.getPredicates().add(optional));
+        result.getPredicates().add(expression);
         return result;
     }
     
-    /**
-     * Find not contains null literals expression.
-     *
-     * @param expression ExpressionSegment
-     * @return expression which not contains null literals
-     */
-    public static Optional<ExpressionSegment> findNotContainsNullLiteralsExpression(final ExpressionSegment expression) {
-        if (isContainsNullLiterals(expression)) {
-            return Optional.empty();
-        }
-        if (expression instanceof BinaryOperationExpression && isContainsNullLiterals(((BinaryOperationExpression) expression).getRight())) {
-            return Optional.empty();
-        }
-        return Optional.ofNullable(expression);
-    }
-    
-    private static boolean isContainsNullLiterals(final ExpressionSegment expression) {
-        if (!(expression instanceof LiteralExpressionSegment)) {
-            return false;
-        }
-        String literals = String.valueOf(((LiteralExpressionSegment) expression).getLiterals());
-        return "NULL".equalsIgnoreCase(literals) || "NOT NULL".equalsIgnoreCase(literals);
-    }
-    
     /**
      * Get parameter marker expression collection.
      * 
diff --git a/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/update/update.xml b/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/update/update.xml
index 45a69c9926c..fe99df8c154 100644
--- a/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/update/update.xml
+++ b/shardingsphere-test/shardingsphere-rewrite-test/src/test/resources/scenario/encrypt/case/query-with-cipher/dml/update/update.xml
@@ -76,21 +76,21 @@
 
     <rewrite-assertion id="update_null_to_clear_plain_where_is_null" db-types="MySQL">
         <input sql="UPDATE t_account_bak SET certificate_number = NULL WHERE certificate_number IS NULL" />
-        <output sql="UPDATE t_account_bak SET certificate_number = NULL WHERE certificate_number IS NULL" />
+        <output sql="UPDATE t_account_bak SET certificate_number = NULL WHERE assisted_query_certificate_number IS NULL" />
     </rewrite-assertion>
 
     <rewrite-assertion id="update_null_to_clear_plain_where_is_null_with_multi" db-types="MySQL">
         <input sql="UPDATE t_account_bak SET certificate_number = NULL WHERE certificate_number IS NULL AND status = 'OK' AND certificate_number = '111X'" />
-        <output sql="UPDATE t_account_bak SET certificate_number = NULL WHERE certificate_number IS NULL AND status = 'OK' AND assisted_query_certificate_number = 'assisted_query_111X'" />
+        <output sql="UPDATE t_account_bak SET certificate_number = NULL WHERE assisted_query_certificate_number IS NULL AND status = 'OK' AND assisted_query_certificate_number = 'assisted_query_111X'" />
     </rewrite-assertion>
 
     <rewrite-assertion id="update_null_to_clear_plain_where_is_not_null" db-types="MySQL">
         <input sql="UPDATE t_account_bak SET certificate_number = NULL WHERE certificate_number IS NOT NULL" />
-        <output sql="UPDATE t_account_bak SET certificate_number = NULL WHERE certificate_number IS NOT NULL" />
+        <output sql="UPDATE t_account_bak SET certificate_number = NULL WHERE assisted_query_certificate_number IS NOT NULL" />
     </rewrite-assertion>
 
     <rewrite-assertion id="update_null_to_clear_plain_where_is_not_null_with_multi" db-types="MySQL">
         <input sql="UPDATE t_account_bak SET certificate_number = NULL WHERE certificate_number IS NOT NULL AND status = 'OK' AND certificate_number = '111X'" />
-        <output sql="UPDATE t_account_bak SET certificate_number = NULL WHERE certificate_number IS NOT NULL AND status = 'OK' AND assisted_query_certificate_number = 'assisted_query_111X'" />
+        <output sql="UPDATE t_account_bak SET certificate_number = NULL WHERE assisted_query_certificate_number IS NOT NULL AND status = 'OK' AND assisted_query_certificate_number = 'assisted_query_111X'" />
     </rewrite-assertion>
 </rewrite-assertions>