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 20597fd1b69 Add EncryptPredicateColumnSupportedChecker (#32397)
20597fd1b69 is described below

commit 20597fd1b69639d70f37de1439ecd67e0af355ae
Author: Liang Zhang <[email protected]>
AuthorDate: Sun Aug 4 23:23:05 2024 +0800

    Add EncryptPredicateColumnSupportedChecker (#32397)
---
 .../EncryptPredicateColumnSupportedChecker.java    | 99 ++++++++++++++++++++++
 .../sql/EncryptSupportedSQLCheckersBuilder.java    |  6 +-
 .../EncryptPredicateColumnTokenGenerator.java      | 17 ++--
 ...ncryptPredicateColumnSupportedCheckerTest.java} | 32 ++-----
 .../EncryptPredicateColumnTokenGeneratorTest.java  |  8 --
 5 files changed, 118 insertions(+), 44 deletions(-)

diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptPredicateColumnSupportedChecker.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptPredicateColumnSupportedChecker.java
new file mode 100644
index 00000000000..a76c6816a7f
--- /dev/null
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptPredicateColumnSupportedChecker.java
@@ -0,0 +1,99 @@
+/*
+ * 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.encrypt.checker.sql;
+
+import 
org.apache.shardingsphere.encrypt.exception.metadata.MissingMatchedEncryptQueryAlgorithmException;
+import 
org.apache.shardingsphere.encrypt.rewrite.token.comparator.JoinConditionsEncryptorComparator;
+import org.apache.shardingsphere.encrypt.rule.EncryptRule;
+import org.apache.shardingsphere.encrypt.rule.table.EncryptTable;
+import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
+import 
org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
+import org.apache.shardingsphere.infra.binder.context.type.WhereAvailable;
+import org.apache.shardingsphere.infra.checker.SupportedSQLChecker;
+import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
+import 
org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
+import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.ExpressionSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.AndPredicate;
+import 
org.apache.shardingsphere.sql.parser.statement.core.segment.dml.predicate.WhereSegment;
+import 
org.apache.shardingsphere.sql.parser.statement.core.util.ExpressionExtractUtils;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Predicate column supported checker for encrypt.
+ */
+@HighFrequencyInvocation
+public final class EncryptPredicateColumnSupportedChecker implements 
SupportedSQLChecker<SQLStatementContext, EncryptRule> {
+    
+    @Override
+    public boolean isCheck(final SQLStatementContext sqlStatementContext) {
+        return sqlStatementContext instanceof WhereAvailable && 
!((WhereAvailable) sqlStatementContext).getWhereSegments().isEmpty();
+    }
+    
+    @Override
+    public void check(final EncryptRule encryptRule, final 
ShardingSphereSchema schema, final SQLStatementContext sqlStatementContext) {
+        
ShardingSpherePreconditions.checkState(JoinConditionsEncryptorComparator.isSame(((WhereAvailable)
 sqlStatementContext).getJoinConditions(), encryptRule),
+                () -> new UnsupportedSQLOperationException("Can not use 
different encryptor in join condition"));
+        check(encryptRule, schema, (WhereAvailable) sqlStatementContext);
+    }
+    
+    private void check(final EncryptRule encryptRule, final 
ShardingSphereSchema schema, final WhereAvailable sqlStatementContext) {
+        Map<String, String> columnExpressionTableNames = ((TableAvailable) 
sqlStatementContext).getTablesContext().findTableNames(sqlStatementContext.getColumnSegments(),
 schema);
+        for (ColumnSegment each : sqlStatementContext.getColumnSegments()) {
+            Optional<EncryptTable> encryptTable = 
encryptRule.findEncryptTable(columnExpressionTableNames.getOrDefault(each.getExpression(),
 ""));
+            String columnName = each.getIdentifier().getValue();
+            if (encryptTable.isPresent() && 
encryptTable.get().isEncryptColumn(columnName) && 
includesLike(sqlStatementContext.getWhereSegments(), each)) {
+                String tableName = encryptTable.get().getTable();
+                ShardingSpherePreconditions.checkState(
+                        
encryptTable.get().getEncryptColumn(columnName).getLikeQuery().isPresent(), () 
-> new MissingMatchedEncryptQueryAlgorithmException(tableName, columnName, 
"LIKE"));
+            }
+        }
+    }
+    
+    private boolean includesLike(final Collection<WhereSegment> whereSegments, 
final ColumnSegment targetColumnSegment) {
+        for (WhereSegment each : whereSegments) {
+            Collection<AndPredicate> andPredicates = 
ExpressionExtractUtils.getAndPredicates(each.getExpr());
+            for (AndPredicate andPredicate : andPredicates) {
+                if (isLikeColumnSegment(andPredicate, targetColumnSegment)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+    
+    private boolean isLikeColumnSegment(final AndPredicate andPredicate, final 
ColumnSegment targetColumnSegment) {
+        for (ExpressionSegment each : andPredicate.getPredicates()) {
+            if (each instanceof BinaryOperationExpression
+                    && "LIKE".equalsIgnoreCase(((BinaryOperationExpression) 
each).getOperator()) && isSameColumnSegment(((BinaryOperationExpression) 
each).getLeft(), targetColumnSegment)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    private boolean isSameColumnSegment(final ExpressionSegment columnSegment, 
final ColumnSegment targetColumnSegment) {
+        return columnSegment instanceof ColumnSegment && 
columnSegment.getStartIndex() == targetColumnSegment.getStartIndex() && 
columnSegment.getStopIndex() == targetColumnSegment.getStopIndex();
+    }
+}
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
index 3f89b02ff42..02351510cb6 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
@@ -22,8 +22,8 @@ import org.apache.shardingsphere.encrypt.rule.EncryptRule;
 import org.apache.shardingsphere.infra.checker.SupportedSQLChecker;
 import org.apache.shardingsphere.infra.checker.SupportedSQLCheckersBuilder;
 
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 
 /**
  * Encrypt SQL supported checker factory.
@@ -32,7 +32,9 @@ public final class EncryptSupportedSQLCheckersBuilder 
implements SupportedSQLChe
     
     @Override
     public Collection<SupportedSQLChecker<?, EncryptRule>> 
getSupportedSQLCheckers() {
-        return Collections.singleton(new EncryptOrderByItemSupportedChecker());
+        return Arrays.asList(
+                new EncryptPredicateColumnSupportedChecker(),
+                new EncryptOrderByItemSupportedChecker());
     }
     
     @Override
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/predicate/EncryptPredicateColumnTokenGenerator.java
 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/predicate/EncryptPredicateColumnTokenGenerator.java
index ad9346c09ae..76bec710ddc 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/predicate/EncryptPredicateColumnTokenGenerator.java
+++ 
b/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/predicate/EncryptPredicateColumnTokenGenerator.java
@@ -17,10 +17,9 @@
 
 package org.apache.shardingsphere.encrypt.rewrite.token.generator.predicate;
 
+import com.google.common.base.Preconditions;
 import lombok.Setter;
-import 
org.apache.shardingsphere.encrypt.exception.metadata.MissingMatchedEncryptQueryAlgorithmException;
 import org.apache.shardingsphere.encrypt.rewrite.aware.EncryptRuleAware;
-import 
org.apache.shardingsphere.encrypt.rewrite.token.comparator.JoinConditionsEncryptorComparator;
 import org.apache.shardingsphere.encrypt.rule.EncryptRule;
 import org.apache.shardingsphere.encrypt.rule.column.EncryptColumn;
 import org.apache.shardingsphere.encrypt.rule.column.item.LikeQueryColumnItem;
@@ -33,8 +32,6 @@ import 
org.apache.shardingsphere.infra.binder.context.type.TableAvailable;
 import org.apache.shardingsphere.infra.binder.context.type.WhereAvailable;
 import 
org.apache.shardingsphere.infra.database.core.metadata.database.enums.QuoteCharacter;
 import org.apache.shardingsphere.infra.database.core.type.DatabaseType;
-import 
org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
-import 
org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import 
org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.CollectionSQLTokenGenerator;
 import 
org.apache.shardingsphere.infra.rewrite.sql.token.common.generator.aware.SchemaMetaDataAware;
@@ -74,8 +71,6 @@ public final class EncryptPredicateColumnTokenGenerator 
implements CollectionSQL
     
     @Override
     public Collection<SQLToken> generateSQLTokens(final SQLStatementContext 
sqlStatementContext) {
-        
ShardingSpherePreconditions.checkState(JoinConditionsEncryptorComparator.isSame(((WhereAvailable)
 sqlStatementContext).getJoinConditions(), encryptRule),
-                () -> new UnsupportedSQLOperationException("Can not use 
different encryptor in join condition"));
         Collection<ColumnSegment> columnSegments = ((WhereAvailable) 
sqlStatementContext).getColumnSegments();
         Collection<WhereSegment> whereSegments = ((WhereAvailable) 
sqlStatementContext).getWhereSegments();
         ShardingSphereSchema schema = ((TableAvailable) 
sqlStatementContext).getTablesContext().getSchemaName().map(schemas::get).orElseGet(()
 -> defaultSchema);
@@ -90,21 +85,21 @@ public final class EncryptPredicateColumnTokenGenerator 
implements CollectionSQL
             String tableName = 
columnExpressionTableNames.getOrDefault(each.getExpression(), "");
             Optional<EncryptTable> encryptTable = 
encryptRule.findEncryptTable(tableName);
             if (encryptTable.isPresent() && 
encryptTable.get().isEncryptColumn(each.getIdentifier().getValue())) {
-                
result.add(buildSubstitutableColumnNameToken(encryptTable.get().getTable(), 
encryptTable.get().getEncryptColumn(each.getIdentifier().getValue()), each, 
whereSegments, databaseType));
+                
result.add(buildSubstitutableColumnNameToken(encryptTable.get().getEncryptColumn(each.getIdentifier().getValue()),
 each, whereSegments, databaseType));
             }
         }
         return result;
     }
     
-    private SubstitutableColumnNameToken 
buildSubstitutableColumnNameToken(final String tableName, final EncryptColumn 
encryptColumn,
+    private SubstitutableColumnNameToken 
buildSubstitutableColumnNameToken(final EncryptColumn encryptColumn,
                                                                            
final ColumnSegment columnSegment, final Collection<WhereSegment> 
whereSegments, final DatabaseType databaseType) {
         int startIndex = columnSegment.getOwner().isPresent() ? 
columnSegment.getOwner().get().getStopIndex() + 2 : 
columnSegment.getStartIndex();
         int stopIndex = columnSegment.getStopIndex();
         if (includesLike(whereSegments, columnSegment)) {
-            LikeQueryColumnItem likeQueryColumnItem = 
encryptColumn.getLikeQuery().orElseThrow(
-                    () -> new 
MissingMatchedEncryptQueryAlgorithmException(tableName, 
columnSegment.getIdentifier().getValue(), "LIKE"));
+            Optional<LikeQueryColumnItem> likeQueryColumnItem = 
encryptColumn.getLikeQuery();
+            Preconditions.checkState(likeQueryColumnItem.isPresent());
             return new SubstitutableColumnNameToken(
-                    startIndex, stopIndex, 
createColumnProjections(likeQueryColumnItem.getName(), 
columnSegment.getIdentifier().getQuoteCharacter(), databaseType), databaseType);
+                    startIndex, stopIndex, 
createColumnProjections(likeQueryColumnItem.get().getName(), 
columnSegment.getIdentifier().getQuoteCharacter(), databaseType), databaseType);
         }
         Collection<Projection> columnProjections =
                 encryptColumn.getAssistedQuery().map(optional -> 
createColumnProjections(optional.getName(), 
columnSegment.getIdentifier().getQuoteCharacter(), databaseType))
diff --git 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
 
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptPredicateColumnSupportedCheckerTest.java
similarity index 50%
copy from 
features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
copy to 
features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptPredicateColumnSupportedCheckerTest.java
index 3f89b02ff42..322a8142cde 100644
--- 
a/features/encrypt/core/src/main/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptSupportedSQLCheckersBuilder.java
+++ 
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/checker/sql/EncryptPredicateColumnSupportedCheckerTest.java
@@ -17,31 +17,17 @@
 
 package org.apache.shardingsphere.encrypt.checker.sql;
 
-import org.apache.shardingsphere.encrypt.constant.EncryptOrder;
-import org.apache.shardingsphere.encrypt.rule.EncryptRule;
-import org.apache.shardingsphere.infra.checker.SupportedSQLChecker;
-import org.apache.shardingsphere.infra.checker.SupportedSQLCheckersBuilder;
+import 
org.apache.shardingsphere.encrypt.rewrite.token.generator.fixture.EncryptGeneratorFixtureBuilder;
+import 
org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
+import org.junit.jupiter.api.Test;
 
-import java.util.Collection;
-import java.util.Collections;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 
-/**
- * Encrypt SQL supported checker factory.
- */
-public final class EncryptSupportedSQLCheckersBuilder implements 
SupportedSQLCheckersBuilder<EncryptRule> {
-    
-    @Override
-    public Collection<SupportedSQLChecker<?, EncryptRule>> 
getSupportedSQLCheckers() {
-        return Collections.singleton(new EncryptOrderByItemSupportedChecker());
-    }
-    
-    @Override
-    public int getOrder() {
-        return EncryptOrder.ORDER;
-    }
+class EncryptPredicateColumnSupportedCheckerTest {
     
-    @Override
-    public Class<EncryptRule> getTypeClass() {
-        return EncryptRule.class;
+    @Test
+    void assertGenerateSQLTokensWhenJoinConditionUseDifferentEncryptor() {
+        assertThrows(UnsupportedSQLOperationException.class,
+                () -> new 
EncryptPredicateColumnSupportedChecker().check(EncryptGeneratorFixtureBuilder.createEncryptRule(),
 null, EncryptGeneratorFixtureBuilder.createSelectStatementContext()));
     }
 }
diff --git 
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/predicate/EncryptPredicateColumnTokenGeneratorTest.java
 
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/predicate/EncryptPredicateColumnTokenGeneratorTest.java
index 1794045d48f..f0eeedc0688 100644
--- 
a/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/predicate/EncryptPredicateColumnTokenGeneratorTest.java
+++ 
b/features/encrypt/core/src/test/java/org/apache/shardingsphere/encrypt/rewrite/token/generator/predicate/EncryptPredicateColumnTokenGeneratorTest.java
@@ -18,7 +18,6 @@
 package org.apache.shardingsphere.encrypt.rewrite.token.generator.predicate;
 
 import 
org.apache.shardingsphere.encrypt.rewrite.token.generator.fixture.EncryptGeneratorFixtureBuilder;
-import 
org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
 import org.apache.shardingsphere.infra.rewrite.sql.token.common.pojo.SQLToken;
 import 
org.apache.shardingsphere.infra.rewrite.sql.token.common.pojo.generic.SubstitutableColumnNameToken;
 import org.junit.jupiter.api.BeforeEach;
@@ -29,7 +28,6 @@ import java.util.Collections;
 
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class EncryptPredicateColumnTokenGeneratorTest {
@@ -54,10 +52,4 @@ class EncryptPredicateColumnTokenGeneratorTest {
         assertThat(substitutableColumnNameTokens.size(), is(1));
         assertThat(((SubstitutableColumnNameToken) 
substitutableColumnNameTokens.iterator().next()).toString(null), 
is("pwd_assist"));
     }
-    
-    @Test
-    void assertGenerateSQLTokensWhenJoinConditionUseDifferentEncryptor() {
-        generator.setSchemas(Collections.emptyMap());
-        assertThrows(UnsupportedSQLOperationException.class, () -> 
generator.generateSQLTokens(EncryptGeneratorFixtureBuilder.createSelectStatementContext()));
-    }
 }

Reply via email to