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]


Reply via email to