Skip to content

Commit

Permalink
Add SameEncryptorComparator (#32268)
Browse files Browse the repository at this point in the history
* Add SameEncryptorComparator

* Add SameEncryptorComparator

* Add SameEncryptorComparator
  • Loading branch information
terrymanu authored Jul 25, 2024
1 parent bdcd306 commit b71b583
Show file tree
Hide file tree
Showing 7 changed files with 187 additions and 76 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* 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.rewrite.token.acrosstable;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
import org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
import org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ColumnProjection;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.ColumnSegmentBoundInfo;
import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;

import java.util.Collection;
import java.util.Iterator;

/**
* Insert select columns same encryptor usage checker.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class InsertSelectColumnsSameEncryptorUsageChecker {

/**
* Judge whether all insert select columns use same encryptor or not.
*
* @param insertColumns insert columns
* @param projections projections
* @param encryptRule encrypt rule
* @return same or different encryptors are using
*/
public static boolean isSame(final Collection<ColumnSegment> insertColumns, final Collection<Projection> projections, final EncryptRule encryptRule) {
Iterator<ColumnSegment> insertColumnsIterator = insertColumns.iterator();
Iterator<Projection> projectionIterator = projections.iterator();
while (insertColumnsIterator.hasNext()) {
ColumnSegment columnSegment = insertColumnsIterator.next();
EncryptAlgorithm columnEncryptor = encryptRule.findQueryEncryptor(
columnSegment.getColumnBoundInfo().getOriginalTable().getValue(), columnSegment.getColumnBoundInfo().getOriginalColumn().getValue()).orElse(null);
Projection projection = projectionIterator.next();
ColumnSegmentBoundInfo columnBoundInfo = getColumnSegmentBoundInfo(projection);
EncryptAlgorithm projectionEncryptor = encryptRule.findQueryEncryptor(columnBoundInfo.getOriginalTable().getValue(), columnBoundInfo.getOriginalColumn().getValue()).orElse(null);
if (!SameEncryptorComparator.isSame(columnEncryptor, projectionEncryptor)) {
return false;
}
}
return true;
}

private static ColumnSegmentBoundInfo getColumnSegmentBoundInfo(final Projection projection) {
return projection instanceof ColumnProjection
? new ColumnSegmentBoundInfo(null, null, ((ColumnProjection) projection).getOriginalTable(), ((ColumnProjection) projection).getOriginalColumn())
: new ColumnSegmentBoundInfo(new IdentifierValue(projection.getColumnLabel()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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.rewrite.token.acrosstable;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;
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.generic.bound.ColumnSegmentBoundInfo;

import java.util.Collection;

/**
* Join conditions same encryptor usage checker.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class JoinConditionsSameEncryptorUsageChecker {

/**
* Judge whether all join conditions use same encryptor or not.
*
* @param joinConditions join conditions
* @param encryptRule encrypt rule
* @return same or different encryptors are using
*/
public static boolean isSame(final Collection<BinaryOperationExpression> joinConditions, final EncryptRule encryptRule) {
for (BinaryOperationExpression each : joinConditions) {
if (!(each.getLeft() instanceof ColumnSegment) || !(each.getRight() instanceof ColumnSegment)) {
continue;
}
ColumnSegmentBoundInfo leftColumnInfo = ((ColumnSegment) each.getLeft()).getColumnBoundInfo();
EncryptAlgorithm leftColumnEncryptor = encryptRule.findQueryEncryptor(leftColumnInfo.getOriginalTable().getValue(), leftColumnInfo.getOriginalColumn().getValue()).orElse(null);
ColumnSegmentBoundInfo rightColumnInfo = ((ColumnSegment) each.getRight()).getColumnBoundInfo();
EncryptAlgorithm rightColumnEncryptor = encryptRule.findQueryEncryptor(rightColumnInfo.getOriginalTable().getValue(), rightColumnInfo.getOriginalColumn().getValue()).orElse(null);
if (!SameEncryptorComparator.isSame(leftColumnEncryptor, rightColumnEncryptor)) {
return false;
}
}
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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.rewrite.token.acrosstable;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.shardingsphere.encrypt.spi.EncryptAlgorithm;

/**
* Same encryptor comparator.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class SameEncryptorComparator {

/**
* Compare whether to same encryptor.
*
* @param encryptor1 encryptor 1 to be compared
* @param encryptor2 encryptor 2 to be compared
* @return same or different encryptors
*/
public static boolean isSame(final EncryptAlgorithm encryptor1, final EncryptAlgorithm encryptor2) {
if (null == encryptor1 && null == encryptor2) {
return true;
}
if (null != encryptor1 && null != encryptor2) {
return encryptor1.getType().equals(encryptor2.getType()) && encryptor1.equals(encryptor2);
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
import org.apache.shardingsphere.encrypt.exception.syntax.UnsupportedEncryptSQLException;
import org.apache.shardingsphere.encrypt.rewrite.aware.DatabaseTypeAware;
import org.apache.shardingsphere.encrypt.rewrite.aware.EncryptRuleAware;
import org.apache.shardingsphere.encrypt.rewrite.token.util.EncryptTokenGeneratorUtils;
import org.apache.shardingsphere.encrypt.rewrite.token.acrosstable.JoinConditionsSameEncryptorUsageChecker;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
import org.apache.shardingsphere.encrypt.rule.table.EncryptTable;
import org.apache.shardingsphere.encrypt.rule.column.EncryptColumn;
import org.apache.shardingsphere.encrypt.rule.column.item.LikeQueryColumnItem;
import org.apache.shardingsphere.encrypt.rule.table.EncryptTable;
import org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
import org.apache.shardingsphere.infra.binder.context.segment.select.projection.impl.ColumnProjection;
import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
Expand Down Expand Up @@ -84,7 +84,7 @@ public Collection<SQLToken> generateSQLTokens(final SQLStatementContext sqlState
whereSegments = ((WhereAvailable) sqlStatementContext).getWhereSegments();
joinConditions = ((WhereAvailable) sqlStatementContext).getJoinConditions();
}
ShardingSpherePreconditions.checkState(EncryptTokenGeneratorUtils.isUseSameEncryptor(joinConditions, encryptRule),
ShardingSpherePreconditions.checkState(JoinConditionsSameEncryptorUsageChecker.isSame(joinConditions, encryptRule),
() -> new UnsupportedSQLOperationException("Can not use different encryptor in join condition"));
String defaultSchema = new DatabaseTypeRegistry(sqlStatementContext.getDatabaseType()).getDefaultSchemaName(databaseName);
ShardingSphereSchema schema = ((TableAvailable) sqlStatementContext).getTablesContext().getSchemaName().map(schemas::get).orElseGet(() -> schemas.get(defaultSchema));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import com.google.common.base.Preconditions;
import lombok.Setter;
import org.apache.shardingsphere.encrypt.rewrite.aware.EncryptRuleAware;
import org.apache.shardingsphere.encrypt.rewrite.token.util.EncryptTokenGeneratorUtils;
import org.apache.shardingsphere.encrypt.rewrite.token.acrosstable.InsertSelectColumnsSameEncryptorUsageChecker;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
import org.apache.shardingsphere.encrypt.rule.table.EncryptTable;
import org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
Expand Down Expand Up @@ -65,7 +65,7 @@ public Collection<SQLToken> generateSQLTokens(final InsertStatementContext inser
if (null != insertStatementContext.getInsertSelectContext()) {
Collection<Projection> projections = insertStatementContext.getInsertSelectContext().getSelectStatementContext().getProjectionsContext().getExpandProjections();
ShardingSpherePreconditions.checkState(insertColumns.size() == projections.size(), () -> new UnsupportedSQLOperationException("Column count doesn't match value count."));
ShardingSpherePreconditions.checkState(EncryptTokenGeneratorUtils.isUseSameEncryptor(insertColumns, projections, encryptRule),
ShardingSpherePreconditions.checkState(InsertSelectColumnsSameEncryptorUsageChecker.isSame(insertColumns, projections, encryptRule),
() -> new UnsupportedSQLOperationException("Can not use different encryptor in insert select columns"));
}
EncryptTable encryptTable = encryptRule.getEncryptTable(insertStatementContext.getSqlStatement().getTable().getTableName().getIdentifier().getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
import com.google.common.base.Preconditions;
import lombok.Setter;
import org.apache.shardingsphere.encrypt.rewrite.aware.EncryptRuleAware;
import org.apache.shardingsphere.encrypt.rewrite.token.util.EncryptTokenGeneratorUtils;
import org.apache.shardingsphere.encrypt.rewrite.token.acrosstable.InsertSelectColumnsSameEncryptorUsageChecker;
import org.apache.shardingsphere.encrypt.rule.EncryptRule;
import org.apache.shardingsphere.encrypt.rule.table.EncryptTable;
import org.apache.shardingsphere.encrypt.rule.column.EncryptColumn;
import org.apache.shardingsphere.encrypt.rule.table.EncryptTable;
import org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
import org.apache.shardingsphere.infra.binder.context.statement.SQLStatementContext;
import org.apache.shardingsphere.infra.binder.context.statement.dml.InsertStatementContext;
Expand Down Expand Up @@ -90,7 +90,7 @@ private UseDefaultInsertColumnsToken generateNewSQLToken(final InsertStatementCo
Collection<ColumnSegment> derivedInsertColumns = insertStatementContext.getSqlStatement().getDerivedInsertColumns();
Collection<Projection> projections = insertStatementContext.getInsertSelectContext().getSelectStatementContext().getProjectionsContext().getExpandProjections();
ShardingSpherePreconditions.checkState(derivedInsertColumns.size() == projections.size(), () -> new UnsupportedSQLOperationException("Column count doesn't match value count."));
ShardingSpherePreconditions.checkState(EncryptTokenGeneratorUtils.isUseSameEncryptor(derivedInsertColumns, projections, encryptRule),
ShardingSpherePreconditions.checkState(InsertSelectColumnsSameEncryptorUsageChecker.isSame(derivedInsertColumns, projections, encryptRule),
() -> new UnsupportedSQLOperationException("Can not use different encryptor in insert select columns"));
}
return new UseDefaultInsertColumnsToken(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,10 @@
import org.apache.shardingsphere.infra.binder.context.statement.dml.SelectStatementContext;
import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
import org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.column.ColumnSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.combine.CombineSegment;
import org.apache.shardingsphere.sql.parser.statement.core.segment.dml.expr.BinaryOperationExpression;
import org.apache.shardingsphere.sql.parser.statement.core.segment.generic.bound.ColumnSegmentBoundInfo;
import org.apache.shardingsphere.sql.parser.statement.core.value.identifier.IdentifierValue;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;

/**
Expand All @@ -42,70 +38,6 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class EncryptTokenGeneratorUtils {

/**
* Judge whether all join conditions use same encryptor or not.
*
* @param joinConditions join conditions
* @param encryptRule encrypt rule
* @return whether all join conditions use same encryptor or not
*/
public static boolean isUseSameEncryptor(final Collection<BinaryOperationExpression> joinConditions, final EncryptRule encryptRule) {
for (BinaryOperationExpression each : joinConditions) {
if (!(each.getLeft() instanceof ColumnSegment) || !(each.getRight() instanceof ColumnSegment)) {
continue;
}
ColumnSegmentBoundInfo leftColumnInfo = ((ColumnSegment) each.getLeft()).getColumnBoundInfo();
EncryptAlgorithm leftColumnEncryptor = encryptRule.findQueryEncryptor(leftColumnInfo.getOriginalTable().getValue(), leftColumnInfo.getOriginalColumn().getValue()).orElse(null);
ColumnSegmentBoundInfo rightColumnInfo = ((ColumnSegment) each.getRight()).getColumnBoundInfo();
EncryptAlgorithm rightColumnEncryptor = encryptRule.findQueryEncryptor(rightColumnInfo.getOriginalTable().getValue(), rightColumnInfo.getOriginalColumn().getValue()).orElse(null);
if (isDifferentEncryptor(leftColumnEncryptor, rightColumnEncryptor)) {
return false;
}
}
return true;
}

/**
* Judge whether all insert select columns use same encryptor or not.
*
* @param insertColumns insert columns
* @param projections projections
* @param encryptRule encrypt rule
* @return whether all insert select columns use same encryptor or not
*/
public static boolean isUseSameEncryptor(final Collection<ColumnSegment> insertColumns, final Collection<Projection> projections, final EncryptRule encryptRule) {
Iterator<ColumnSegment> insertColumnsIterator = insertColumns.iterator();
Iterator<Projection> projectionIterator = projections.iterator();
while (insertColumnsIterator.hasNext()) {
ColumnSegment columnSegment = insertColumnsIterator.next();
EncryptAlgorithm leftColumnEncryptor = encryptRule.findQueryEncryptor(
columnSegment.getColumnBoundInfo().getOriginalTable().getValue(), columnSegment.getColumnBoundInfo().getOriginalColumn().getValue()).orElse(null);
Projection projection = projectionIterator.next();
ColumnSegmentBoundInfo columnBoundInfo = getColumnSegmentBoundInfo(projection);
EncryptAlgorithm rightColumnEncryptor = encryptRule.findQueryEncryptor(columnBoundInfo.getOriginalTable().getValue(), columnBoundInfo.getOriginalColumn().getValue()).orElse(null);
if (isDifferentEncryptor(leftColumnEncryptor, rightColumnEncryptor)) {
return false;
}
}
return true;
}

private static ColumnSegmentBoundInfo getColumnSegmentBoundInfo(final Projection projection) {
return projection instanceof ColumnProjection
? new ColumnSegmentBoundInfo(null, null, ((ColumnProjection) projection).getOriginalTable(), ((ColumnProjection) projection).getOriginalColumn())
: new ColumnSegmentBoundInfo(new IdentifierValue(projection.getColumnLabel()));
}

private static boolean isDifferentEncryptor(final EncryptAlgorithm leftColumnEncryptor, final EncryptAlgorithm rightColumnEncryptor) {
if (null != leftColumnEncryptor && null != rightColumnEncryptor) {
if (!leftColumnEncryptor.getType().equals(rightColumnEncryptor.getType())) {
return true;
}
return !leftColumnEncryptor.equals(rightColumnEncryptor);
}
return null != leftColumnEncryptor || null != rightColumnEncryptor;
}

/**
* Judge whether contains encrypt projection in combine statement or not.
*
Expand Down Expand Up @@ -134,4 +66,10 @@ public static boolean containsEncryptProjectionInCombineStatement(final SelectSt
}
return false;
}

private static ColumnSegmentBoundInfo getColumnSegmentBoundInfo(final Projection projection) {
return projection instanceof ColumnProjection
? new ColumnSegmentBoundInfo(null, null, ((ColumnProjection) projection).getOriginalTable(), ((ColumnProjection) projection).getOriginalColumn())
: new ColumnSegmentBoundInfo(new IdentifierValue(projection.getColumnLabel()));
}
}

0 comments on commit b71b583

Please sign in to comment.