wgy8283335 commented on a change in pull request #8310:
URL: https://github.com/apache/shardingsphere/pull/8310#discussion_r532297530
##########
File path:
shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/validator/dml/impl/ShardingInsertStatementValidator.java
##########
@@ -84,6 +103,94 @@ private boolean isContainsKeyGenerateColumn(final
ShardingRule shardingRule, fin
private boolean isAllSameTables(final Collection<String> tableNames) {
return 1 == tableNames.stream().distinct().count();
}
+
+ private void checkSubqueryShardingValues(final ShardingRule shardingRule,
final SQLStatementContext<InsertStatement> sqlStatementContext,
+ final List<Object> parameters, final ShardingSphereSchema schema) {
+ for (String each :
sqlStatementContext.getTablesContext().getTableNames()) {
+ Optional<TableRule> tableRule = shardingRule.findTableRule(each);
+ if (tableRule.isPresent() && isRoutingByHint(shardingRule,
tableRule.get())
+ && !HintManager.getDatabaseShardingValues(each).isEmpty() &&
!HintManager.getTableShardingValues(each).isEmpty()) {
+ return;
+ }
+ }
+ ShardingConditions shardingConditions =
createShardingConditions(sqlStatementContext, parameters, schema, shardingRule);
+ if (shardingConditions.getConditions().size() > 1) {
+ Preconditions.checkState(isSameShardingCondition(shardingRule,
shardingConditions), "Sharding value must same with subquery.");
+ }
+ }
+
+ private boolean isRoutingByHint(final ShardingRule shardingRule, final
TableRule tableRule) {
+ return
shardingRule.getDatabaseShardingStrategyConfiguration(tableRule) instanceof
HintShardingStrategyConfiguration
+ && shardingRule.getTableShardingStrategyConfiguration(tableRule)
instanceof HintShardingStrategyConfiguration;
+ }
+
+ private boolean isSameShardingCondition(final ShardingRule shardingRule,
final ShardingConditions shardingConditions) {
+ ShardingCondition example =
shardingConditions.getConditions().remove(shardingConditions.getConditions().size()
- 1);
+ for (ShardingCondition each : shardingConditions.getConditions()) {
+ if (!isSameShardingCondition(shardingRule, example, each)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isSameShardingCondition(final ShardingRule shardingRule,
final ShardingCondition shardingCondition1, final ShardingCondition
shardingCondition2) {
+ if (shardingCondition1.getValues().size() !=
shardingCondition2.getValues().size()) {
+ return false;
+ }
+ for (int i = 0; i < shardingCondition1.getValues().size(); i++) {
+ ShardingConditionValue shardingConditionValue1 =
shardingCondition1.getValues().get(i);
+ ShardingConditionValue shardingConditionValue2 =
shardingCondition2.getValues().get(i);
+ if (!isSameShardingConditionValue(shardingRule,
shardingConditionValue1, shardingConditionValue2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean isSameShardingConditionValue(final ShardingRule
shardingRule, final ShardingConditionValue shardingConditionValue1, final
ShardingConditionValue shardingConditionValue2) {
+ return isSameLogicTable(shardingRule, shardingConditionValue1,
shardingConditionValue2) &&
shardingConditionValue1.getColumnName().equals(shardingConditionValue2.getColumnName())
+ && isSameValue(shardingConditionValue1, shardingConditionValue2);
+ }
+
+ private boolean isSameLogicTable(final ShardingRule shardingRule, final
ShardingConditionValue shardingValue1, final ShardingConditionValue
shardingValue2) {
+ return
shardingValue1.getTableName().equals(shardingValue2.getTableName()) ||
isBindingTable(shardingRule, shardingValue1, shardingValue2);
+ }
+
+ private boolean isBindingTable(final ShardingRule shardingRule, final
ShardingConditionValue shardingValue1, final ShardingConditionValue
shardingValue2) {
+ Optional<BindingTableRule> bindingRule =
shardingRule.findBindingTableRule(shardingValue1.getTableName());
+ return bindingRule.isPresent() &&
bindingRule.get().hasLogicTable(shardingValue2.getTableName());
+ }
+
+ @SuppressWarnings({"rawtypes", "unchecked"})
+ private boolean isSameValue(final ShardingConditionValue
shardingConditionValue1, final ShardingConditionValue shardingConditionValue2) {
+ if (shardingConditionValue1 instanceof ListShardingConditionValue &&
shardingConditionValue2 instanceof ListShardingConditionValue) {
+ return SafeNumberOperationUtils.safeCollectionEquals(
+ ((ListShardingConditionValue)
shardingConditionValue1).getValues(), ((ListShardingConditionValue)
shardingConditionValue2).getValues());
+ } else if (shardingConditionValue1 instanceof
RangeShardingConditionValue && shardingConditionValue2 instanceof
RangeShardingConditionValue) {
+ return SafeNumberOperationUtils.safeRangeEquals(
+ ((RangeShardingConditionValue)
shardingConditionValue1).getValueRange(), ((RangeShardingConditionValue)
shardingConditionValue2).getValueRange());
+ }
+ return false;
+ }
+
+ private ShardingConditions createShardingConditions(final
SQLStatementContext<InsertStatement> sqlStatementContext,
+ final List<Object> parameters, final ShardingSphereSchema schema,
final ShardingRule rule) {
+ List<ShardingCondition> shardingConditions;
+ if (sqlStatementContext.getSqlStatement() instanceof DMLStatement) {
+ ShardingConditionEngine shardingConditionEngine = new
WhereClauseShardingConditionEngine(rule, schema);
+ shardingConditions =
shardingConditionEngine.createShardingConditions(sqlStatementContext,
parameters);
+ } else {
+ shardingConditions = Collections.emptyList();
+ }
+ return new ShardingConditions(shardingConditions);
+ }
+
+ private boolean isNeedMergeShardingValues(final SQLStatementContext<?>
sqlStatementContext, final ShardingRule rule) {
+ boolean insertSelectContainsSubquery = sqlStatementContext instanceof
InsertStatementContext && null != ((InsertStatementContext)
sqlStatementContext).getInsertSelectContext()
+ && ((InsertStatementContext)
sqlStatementContext).getInsertSelectContext().getSelectStatementContext().isContainsSubquery();
Review comment:
I think to move this method to the ShardingDMLStatementValidator is
better.
----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
For queries about this service, please contact Infrastructure at:
[email protected]