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()));
- }
}