This is an automated email from the ASF dual-hosted git repository.

zhangliang 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 1a8c14030a7 Refactor shadow column condition iterator in shadow route 
engine (#20466)
1a8c14030a7 is described below

commit 1a8c14030a7865b645507a4325c6b79272299326
Author: gin <[email protected]>
AuthorDate: Wed Aug 24 15:15:24 2022 +0800

    Refactor shadow column condition iterator in shadow route engine (#20466)
    
    * Refactor shadow column condition iterator in shadow route engine
    
    * Fix CI
---
 .../dml/AbstractShadowDMLStatementRouteEngine.java | 25 ++++++--
 ...tWhereSegmentShadowColumnConditionIterator.java | 69 ++++++++++++++++++++++
 .../dml/ShadowDeleteStatementRoutingEngine.java    | 27 +++------
 .../dml/ShadowInsertStatementRoutingEngine.java    | 25 +++++---
 .../dml/ShadowSelectStatementRoutingEngine.java    | 32 +++-------
 .../dml/ShadowUpdateStatementRoutingEngine.java    | 27 +++------
 .../UnsupportedShadowInsertValueException.java     | 33 +++++++++++
 .../shadow/rule/ShadowAlgorithmNameRule.java       | 33 +++++++++++
 .../shardingsphere/shadow/rule/ShadowRule.java     | 35 +++++++++--
 .../shadow/rule/ShadowTableRule.java               | 20 ++++---
 10 files changed, 234 insertions(+), 92 deletions(-)

diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractShadowDMLStatementRouteEngine.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractShadowDMLStatementRouteEngine.java
index 41b8ffe22d1..9ae821f4e5e 100644
--- 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractShadowDMLStatementRouteEngine.java
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractShadowDMLStatementRouteEngine.java
@@ -119,17 +119,29 @@ public abstract class 
AbstractShadowDMLStatementRouteEngine implements ShadowRou
     private Map<String, String> findByShadowColumn(final Collection<String> 
relatedShadowTables, final ShadowRule shadowRule, final ShadowOperationType 
shadowOperationType) {
         Map<String, String> result = new LinkedHashMap<>();
         for (String each : relatedShadowTables) {
-            Collection<ColumnShadowAlgorithm<Comparable<?>>> 
columnShadowAlgorithms = shadowRule.getRelatedColumnShadowAlgorithms(each, 
shadowOperationType);
-            if (!columnShadowAlgorithms.isEmpty() && 
isMatchAnyColumnShadowAlgorithms(each, columnShadowAlgorithms, shadowRule, 
shadowOperationType)) {
+            Collection<String> relatedShadowColumnNames = 
shadowRule.getRelatedShadowColumnNames(shadowOperationType, each);
+            if (!relatedShadowColumnNames.isEmpty() && 
isMatchAnyColumnShadowAlgorithms(each, relatedShadowColumnNames, shadowRule, 
shadowOperationType)) {
                 return shadowRule.getRelatedShadowDataSourceMappings(each);
             }
         }
         return result;
     }
     
-    private boolean isMatchAnyColumnShadowAlgorithms(final String shadowTable, 
final Collection<ColumnShadowAlgorithm<Comparable<?>>> columnShadowAlgorithms, 
final ShadowRule shadowRule,
-                                                     final ShadowOperationType 
shadowOperationType) {
-        Iterator<Optional<ShadowColumnCondition>> iterator = 
getShadowColumnConditionIterator();
+    private boolean isMatchAnyColumnShadowAlgorithms(final String shadowTable, 
final Collection<String> shadowColumnNames, final ShadowRule shadowRule, final 
ShadowOperationType shadowOperation) {
+        for (String each : shadowColumnNames) {
+            if (isMatchAnyColumnShadowAlgorithms(shadowTable, each, 
shadowOperation, shadowRule)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    private boolean isMatchAnyColumnShadowAlgorithms(final String shadowTable, 
final String shadowColumn, final ShadowOperationType shadowOperationType, final 
ShadowRule shadowRule) {
+        Collection<ColumnShadowAlgorithm<Comparable<?>>> 
columnShadowAlgorithms = 
shadowRule.getRelatedColumnShadowAlgorithms(shadowOperationType, shadowTable, 
shadowColumn);
+        if (columnShadowAlgorithms.isEmpty()) {
+            return false;
+        }
+        Iterator<Optional<ShadowColumnCondition>> iterator = 
getShadowColumnConditionIterator(shadowColumn);
         ShadowDetermineCondition shadowDetermineCondition;
         while (iterator.hasNext()) {
             Optional<ShadowColumnCondition> next = iterator.next();
@@ -169,9 +181,10 @@ public abstract class 
AbstractShadowDMLStatementRouteEngine implements ShadowRou
     /**
      * Get shadow column condition iterator.
      *
+     * @param shadowColumn shadow column
      * @return shadow column condition iterator
      */
-    protected abstract Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator();
+    protected abstract Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator(String shadowColumn);
     
     /**
      * Get single table tame.
diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractWhereSegmentShadowColumnConditionIterator.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractWhereSegmentShadowColumnConditionIterator.java
new file mode 100644
index 00000000000..3f145c240d0
--- /dev/null
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/AbstractWhereSegmentShadowColumnConditionIterator.java
@@ -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.shadow.route.engine.dml;
+
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.shadow.condition.ShadowColumnCondition;
+import org.apache.shardingsphere.shadow.route.engine.util.ShadowExtractor;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+/**
+ * Abstract shadow column condition iterator of where segment.
+ */
+@RequiredArgsConstructor
+@Getter(value = AccessLevel.PROTECTED)
+public abstract class AbstractWhereSegmentShadowColumnConditionIterator 
implements Iterator<Optional<ShadowColumnCondition>> {
+    
+    private final String shadowColumn;
+    
+    private final Iterator<ExpressionSegment> iterator;
+    
+    @Override
+    public boolean hasNext() {
+        return iterator.hasNext();
+    }
+    
+    @Override
+    public Optional<ShadowColumnCondition> next() {
+        ExpressionSegment expressionSegment = iterator.next();
+        Optional<ColumnSegment> columnSegment = 
ShadowExtractor.extractColumn(expressionSegment);
+        if (!columnSegment.isPresent()) {
+            return Optional.empty();
+        }
+        String column = columnSegment.get().getIdentifier().getValue();
+        if (!shadowColumn.equals(column)) {
+            return Optional.empty();
+        }
+        return nextShadowColumnCondition(expressionSegment, 
columnSegment.get());
+    }
+    
+    /**
+     * Next shadow column condition.
+     *
+     * @param expressionSegment expression segment
+     * @param columnSegment column segment
+     * @return shadow column condition
+     */
+    protected abstract Optional<ShadowColumnCondition> 
nextShadowColumnCondition(ExpressionSegment expressionSegment, ColumnSegment 
columnSegment);
+}
diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowDeleteStatementRoutingEngine.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowDeleteStatementRoutingEngine.java
index 37bf1fbf79a..84f1689be74 100644
--- 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowDeleteStatementRoutingEngine.java
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowDeleteStatementRoutingEngine.java
@@ -22,6 +22,7 @@ import 
org.apache.shardingsphere.infra.binder.statement.dml.DeleteStatementConte
 import org.apache.shardingsphere.shadow.api.shadow.ShadowOperationType;
 import org.apache.shardingsphere.shadow.condition.ShadowColumnCondition;
 import org.apache.shardingsphere.shadow.route.engine.util.ShadowExtractor;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
@@ -62,8 +63,8 @@ public final class ShadowDeleteStatementRoutingEngine extends 
AbstractShadowDMLS
     }
     
     @Override
-    protected Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator() {
-        return new ShadowColumnConditionIterator(parseWhereSegment(), 
parameters);
+    protected Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator(final String shadowColumn) {
+        return new ShadowColumnConditionIterator(shadowColumn, 
parseWhereSegment());
     }
     
     private Collection<ExpressionSegment> parseWhereSegment() {
@@ -76,27 +77,15 @@ public final class ShadowDeleteStatementRoutingEngine 
extends AbstractShadowDMLS
         return result;
     }
     
-    private class ShadowColumnConditionIterator implements 
Iterator<Optional<ShadowColumnCondition>> {
+    private final class ShadowColumnConditionIterator extends 
AbstractWhereSegmentShadowColumnConditionIterator {
         
-        private final Iterator<ExpressionSegment> iterator;
-        
-        private final List<Object> parameters;
-        
-        ShadowColumnConditionIterator(final Collection<ExpressionSegment> 
predicates, final List<Object> parameters) {
-            this.iterator = predicates.iterator();
-            this.parameters = parameters;
-        }
-        
-        @Override
-        public boolean hasNext() {
-            return iterator.hasNext();
+        ShadowColumnConditionIterator(final String shadowColumn, final 
Collection<ExpressionSegment> predicates) {
+            super(shadowColumn, predicates.iterator());
         }
         
         @Override
-        public Optional<ShadowColumnCondition> next() {
-            ExpressionSegment expressionSegment = iterator.next();
-            return 
ShadowExtractor.extractColumn(expressionSegment).flatMap(optional -> 
ShadowExtractor.extractValues(expressionSegment, parameters)
-                    .map(values -> new 
ShadowColumnCondition(getSingleTableName(), 
optional.getIdentifier().getValue(), values)));
+        protected Optional<ShadowColumnCondition> 
nextShadowColumnCondition(final ExpressionSegment expressionSegment, final 
ColumnSegment columnSegment) {
+            return ShadowExtractor.extractValues(expressionSegment, 
parameters).map(values -> new ShadowColumnCondition(getSingleTableName(), 
getShadowColumn(), values));
         }
     }
 }
diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowInsertStatementRoutingEngine.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowInsertStatementRoutingEngine.java
index 5d8a26fb8a8..655497c0069 100644
--- 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowInsertStatementRoutingEngine.java
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowInsertStatementRoutingEngine.java
@@ -22,6 +22,7 @@ import 
org.apache.shardingsphere.infra.binder.segment.insert.values.InsertValueC
 import 
org.apache.shardingsphere.infra.binder.statement.dml.InsertStatementContext;
 import org.apache.shardingsphere.shadow.api.shadow.ShadowOperationType;
 import org.apache.shardingsphere.shadow.condition.ShadowColumnCondition;
+import 
org.apache.shardingsphere.shadow.route.exception.UnsupportedShadowInsertValueException;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
 
 import java.util.Collection;
@@ -56,8 +57,8 @@ public final class ShadowInsertStatementRoutingEngine extends 
AbstractShadowDMLS
     }
     
     @Override
-    protected Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator() {
-        return new 
ShadowColumnConditionIterator(parseColumnNames().iterator(), 
insertStatementContext.getInsertValueContexts());
+    protected Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator(final String shadowColumn) {
+        return new ShadowColumnConditionIterator(shadowColumn, 
parseColumnNames().iterator(), insertStatementContext.getInsertValueContexts());
     }
     
     private Collection<String> parseColumnNames() {
@@ -68,14 +69,17 @@ public final class ShadowInsertStatementRoutingEngine 
extends AbstractShadowDMLS
         
         private int index;
         
+        private final String shadowColumn;
+        
         private final Iterator<String> iterator;
         
         private final List<InsertValueContext> insertValueContexts;
         
-        ShadowColumnConditionIterator(final Iterator<String> iterator, final 
List<InsertValueContext> insertValueContexts) {
+        ShadowColumnConditionIterator(final String shadowColumn, final 
Iterator<String> iterator, final List<InsertValueContext> insertValueContexts) {
+            index = 0;
+            this.shadowColumn = shadowColumn;
             this.iterator = iterator;
             this.insertValueContexts = insertValueContexts;
-            this.index = 0;
         }
         
         @Override
@@ -86,17 +90,21 @@ public final class ShadowInsertStatementRoutingEngine 
extends AbstractShadowDMLS
         @Override
         public Optional<ShadowColumnCondition> next() {
             String columnName = iterator.next();
+            if (!shadowColumn.equals(columnName)) {
+                index++;
+                return Optional.empty();
+            }
             Optional<Collection<Comparable<?>>> columnValues = 
getColumnValues(insertValueContexts, index);
             index++;
             return columnValues.map(each -> new 
ShadowColumnCondition(getSingleTableName(), columnName, each));
         }
         
-        private Optional<Collection<Comparable<?>>> getColumnValues(final 
List<InsertValueContext> insertValueContexts, final int index) {
+        private Optional<Collection<Comparable<?>>> getColumnValues(final 
List<InsertValueContext> insertValueContexts, final int columnIndex) {
             Collection<Comparable<?>> result = new LinkedList<>();
             for (InsertValueContext each : insertValueContexts) {
-                Optional<Object> valueObject = each.getLiteralValue(index);
-                if (valueObject.isPresent() && valueObject.get() instanceof 
Comparable<?>) {
-                    result.add((Comparable<?>) valueObject.get());
+                Object valueObject = 
each.getLiteralValue(columnIndex).orElseThrow(() -> new 
UnsupportedShadowInsertValueException(columnIndex));
+                if (valueObject instanceof Comparable<?>) {
+                    result.add((Comparable<?>) valueObject);
                 } else {
                     return Optional.empty();
                 }
@@ -104,5 +112,4 @@ public final class ShadowInsertStatementRoutingEngine 
extends AbstractShadowDMLS
             return result.isEmpty() ? Optional.empty() : Optional.of(result);
         }
     }
-    
 }
diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRoutingEngine.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRoutingEngine.java
index 9e42795e1e3..fe2479d6ac7 100644
--- 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRoutingEngine.java
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowSelectStatementRoutingEngine.java
@@ -64,8 +64,8 @@ public final class ShadowSelectStatementRoutingEngine extends 
AbstractShadowDMLS
     }
     
     @Override
-    protected Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator() {
-        return new ShadowColumnConditionIterator(parseWhereSegment(), 
parameters);
+    protected Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator(final String shadowColumn) {
+        return new ShadowColumnConditionIterator(shadowColumn, 
parseWhereSegment());
     }
     
     private Collection<ExpressionSegment> parseWhereSegment() {
@@ -78,33 +78,15 @@ public final class ShadowSelectStatementRoutingEngine 
extends AbstractShadowDMLS
         return result;
     }
     
-    private class ShadowColumnConditionIterator implements 
Iterator<Optional<ShadowColumnCondition>> {
+    private final class ShadowColumnConditionIterator extends 
AbstractWhereSegmentShadowColumnConditionIterator {
         
-        private final Iterator<ExpressionSegment> iterator;
-        
-        private final List<Object> parameters;
-        
-        ShadowColumnConditionIterator(final Collection<ExpressionSegment> 
predicates, final List<Object> parameters) {
-            this.iterator = predicates.iterator();
-            this.parameters = parameters;
-        }
-        
-        @Override
-        public boolean hasNext() {
-            return iterator.hasNext();
+        ShadowColumnConditionIterator(final String shadowColumn, final 
Collection<ExpressionSegment> predicates) {
+            super(shadowColumn, predicates.iterator());
         }
         
         @Override
-        public Optional<ShadowColumnCondition> next() {
-            ExpressionSegment expressionSegment = iterator.next();
-            Optional<ColumnSegment> columnSegment = 
ShadowExtractor.extractColumn(expressionSegment);
-            if (columnSegment.isPresent()) {
-                Optional<Collection<Comparable<?>>> values = 
ShadowExtractor.extractValues(expressionSegment, parameters);
-                if (values.isPresent()) {
-                    return Optional.of(new 
ShadowColumnCondition(extractOwnerName(columnSegment.get()), 
columnSegment.get().getIdentifier().getValue(), values.get()));
-                }
-            }
-            return Optional.empty();
+        protected Optional<ShadowColumnCondition> 
nextShadowColumnCondition(final ExpressionSegment expressionSegment, final 
ColumnSegment columnSegment) {
+            return ShadowExtractor.extractValues(expressionSegment, 
parameters).map(values -> new 
ShadowColumnCondition(extractOwnerName(columnSegment), getShadowColumn(), 
values));
         }
         
         private String extractOwnerName(final ColumnSegment columnSegment) {
diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowUpdateStatementRoutingEngine.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowUpdateStatementRoutingEngine.java
index b52c142b87f..7219a0d4540 100644
--- 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowUpdateStatementRoutingEngine.java
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/engine/dml/ShadowUpdateStatementRoutingEngine.java
@@ -22,6 +22,7 @@ import 
org.apache.shardingsphere.infra.binder.statement.dml.UpdateStatementConte
 import org.apache.shardingsphere.shadow.api.shadow.ShadowOperationType;
 import org.apache.shardingsphere.shadow.condition.ShadowColumnCondition;
 import org.apache.shardingsphere.shadow.route.engine.util.ShadowExtractor;
+import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.column.ColumnSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.expr.ExpressionSegment;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.AndPredicate;
 import 
org.apache.shardingsphere.sql.parser.sql.common.segment.dml.predicate.WhereSegment;
@@ -62,8 +63,8 @@ public final class ShadowUpdateStatementRoutingEngine extends 
AbstractShadowDMLS
     }
     
     @Override
-    protected Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator() {
-        return new ShadowColumnConditionIterator(parseWhereSegment(), 
parameters);
+    protected Iterator<Optional<ShadowColumnCondition>> 
getShadowColumnConditionIterator(final String shadowColumn) {
+        return new ShadowColumnConditionIterator(shadowColumn, 
parseWhereSegment());
     }
     
     private Collection<ExpressionSegment> parseWhereSegment() {
@@ -76,27 +77,15 @@ public final class ShadowUpdateStatementRoutingEngine 
extends AbstractShadowDMLS
         return result;
     }
     
-    private class ShadowColumnConditionIterator implements 
Iterator<Optional<ShadowColumnCondition>> {
+    private final class ShadowColumnConditionIterator extends 
AbstractWhereSegmentShadowColumnConditionIterator {
         
-        private final Iterator<ExpressionSegment> iterator;
-        
-        private final List<Object> parameters;
-        
-        ShadowColumnConditionIterator(final Collection<ExpressionSegment> 
predicates, final List<Object> parameters) {
-            this.iterator = predicates.iterator();
-            this.parameters = parameters;
-        }
-        
-        @Override
-        public boolean hasNext() {
-            return iterator.hasNext();
+        ShadowColumnConditionIterator(final String shadowColumn, final 
Collection<ExpressionSegment> predicates) {
+            super(shadowColumn, predicates.iterator());
         }
         
         @Override
-        public Optional<ShadowColumnCondition> next() {
-            ExpressionSegment expressionSegment = iterator.next();
-            return 
ShadowExtractor.extractColumn(expressionSegment).flatMap(optional -> 
ShadowExtractor.extractValues(expressionSegment, parameters)
-                    .map(values -> new 
ShadowColumnCondition(getSingleTableName(), 
optional.getIdentifier().getValue(), values)));
+        protected Optional<ShadowColumnCondition> 
nextShadowColumnCondition(final ExpressionSegment expressionSegment, final 
ColumnSegment columnSegment) {
+            return ShadowExtractor.extractValues(expressionSegment, 
parameters).map(values -> new ShadowColumnCondition(getSingleTableName(), 
getShadowColumn(), values));
         }
     }
 }
diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/exception/UnsupportedShadowInsertValueException.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/exception/UnsupportedShadowInsertValueException.java
new file mode 100644
index 00000000000..f861d5bab1c
--- /dev/null
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/route/exception/UnsupportedShadowInsertValueException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.shadow.route.exception;
+
+import 
org.apache.shardingsphere.infra.util.exception.sql.ShardingSphereSQLException;
+import 
org.apache.shardingsphere.infra.util.exception.sql.sqlstate.XOpenSQLState;
+
+/**
+ * Unsupported shadow insert value exception.
+ */
+public final class UnsupportedShadowInsertValueException extends 
ShardingSphereSQLException {
+    
+    private static final long serialVersionUID = -5987403907441367171L;
+    
+    public UnsupportedShadowInsertValueException(final int columnIndex) {
+        super(XOpenSQLState.SYNTAX_ERROR, 25003, "Insert value of index `%s` 
can not support for shadow", String.valueOf(columnIndex));
+    }
+}
diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowAlgorithmNameRule.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowAlgorithmNameRule.java
new file mode 100644
index 00000000000..928af90da73
--- /dev/null
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowAlgorithmNameRule.java
@@ -0,0 +1,33 @@
+/*
+ * 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.shadow.rule;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+/**
+ * Shadow algorithm name rule.
+ */
+@RequiredArgsConstructor
+@Getter
+public final class ShadowAlgorithmNameRule {
+    
+    private final String shadowColumnName;
+    
+    private final String shadowAlgorithmName;
+}
diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java
index ad6ade56799..bf07b0b925e 100644
--- 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowRule.java
@@ -176,20 +176,43 @@ public final class ShadowRule implements DatabaseRule, 
DataSourceContainedRule {
     /**
      * Get related column shadow algorithms by table name.
      *
-     * @param tableName table name
      * @param shadowOperationType shadow operation type
+     * @param tableName table name
+     * @param shadowColumn shadow column
      * @return column shadow algorithms
      */
     @SuppressWarnings("unchecked")
-    public Collection<ColumnShadowAlgorithm<Comparable<?>>> 
getRelatedColumnShadowAlgorithms(final String tableName, final 
ShadowOperationType shadowOperationType) {
+    public Collection<ColumnShadowAlgorithm<Comparable<?>>> 
getRelatedColumnShadowAlgorithms(final ShadowOperationType shadowOperationType, 
final String tableName, final String shadowColumn) {
         Collection<ColumnShadowAlgorithm<Comparable<?>>> result = new 
LinkedList<>();
-        Map<ShadowOperationType, Collection<String>> 
columnShadowAlgorithmNames = 
shadowTableRules.get(tableName).getColumnShadowAlgorithmNames();
-        Collection<String> names = 
columnShadowAlgorithmNames.get(shadowOperationType);
+        Map<ShadowOperationType, Collection<ShadowAlgorithmNameRule>> 
columnShadowAlgorithmNames = 
shadowTableRules.get(tableName).getColumnShadowAlgorithmNames();
+        Collection<ShadowAlgorithmNameRule> names = 
columnShadowAlgorithmNames.get(shadowOperationType);
+        if (Objects.isNull(names)) {
+            return result;
+        }
+        for (ShadowAlgorithmNameRule each : names) {
+            if (shadowColumn.equals(each.getShadowColumnName())) {
+                result.add((ColumnShadowAlgorithm<Comparable<?>>) 
shadowAlgorithms.get(each.getShadowAlgorithmName()));
+            }
+        }
+        return result;
+    }
+    
+    /**
+     * Get related shadow column names.
+     *
+     * @param shadowOperationType shadow operation type
+     * @param tableName table name
+     * @return related shadow column names
+     */
+    public Collection<String> getRelatedShadowColumnNames(final 
ShadowOperationType shadowOperationType, final String tableName) {
+        Collection<String> result = new LinkedList<>();
+        Map<ShadowOperationType, Collection<ShadowAlgorithmNameRule>> 
columnShadowAlgorithmNames = 
shadowTableRules.get(tableName).getColumnShadowAlgorithmNames();
+        Collection<ShadowAlgorithmNameRule> names = 
columnShadowAlgorithmNames.get(shadowOperationType);
         if (Objects.isNull(names)) {
             return result;
         }
-        for (String each : names) {
-            result.add((ColumnShadowAlgorithm<Comparable<?>>) 
shadowAlgorithms.get(each));
+        for (ShadowAlgorithmNameRule each : names) {
+            result.add(each.getShadowColumnName());
         }
         return result;
     }
diff --git 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowTableRule.java
 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowTableRule.java
index 3e11285f045..be3787c6dba 100644
--- 
a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowTableRule.java
+++ 
b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-core/src/main/java/org/apache/shardingsphere/shadow/rule/ShadowTableRule.java
@@ -42,7 +42,7 @@ public final class ShadowTableRule {
     
     private final Collection<String> hintShadowAlgorithmNames;
     
-    private final Map<ShadowOperationType, Collection<String>> 
columnShadowAlgorithmNames;
+    private final Map<ShadowOperationType, 
Collection<ShadowAlgorithmNameRule>> columnShadowAlgorithmNames;
     
     public ShadowTableRule(final String tableName, final Collection<String> 
shadowDataSources, final Collection<String> shadowAlgorithmNames, final 
Map<String, ShadowAlgorithm> shadowAlgorithms) {
         this.tableName = tableName;
@@ -55,20 +55,24 @@ public final class ShadowTableRule {
         return shadowAlgorithmNames.stream().filter(each -> 
shadowAlgorithms.get(each) instanceof 
HintShadowAlgorithm).collect(Collectors.toList());
     }
     
-    private Map<ShadowOperationType, Collection<String>> 
initColumnShadowAlgorithmNames(final Collection<String> shadowAlgorithmNames, 
final Map<String, ShadowAlgorithm> shadowAlgorithms) {
-        Map<ShadowOperationType, Collection<String>> result = new 
EnumMap<>(ShadowOperationType.class);
+    private Map<ShadowOperationType, Collection<ShadowAlgorithmNameRule>> 
initColumnShadowAlgorithmNames(final Collection<String> shadowAlgorithmNames,
+                                                                               
                          final Map<String, ShadowAlgorithm> shadowAlgorithms) {
+        Map<ShadowOperationType, Collection<ShadowAlgorithmNameRule>> result = 
new EnumMap<>(ShadowOperationType.class);
         shadowAlgorithmNames.forEach(each -> {
             ShadowAlgorithm shadowAlgorithm = shadowAlgorithms.get(each);
             if (shadowAlgorithm instanceof ColumnShadowAlgorithm) {
-                
ShadowOperationType.contains(shadowAlgorithm.getProps().getProperty("operation")).ifPresent(optional
 -> initShadowAlgorithmNames(result, each, optional));
+                String operation = 
shadowAlgorithm.getProps().getProperty("operation");
+                String shadowColumnName = 
shadowAlgorithm.getProps().getProperty("column");
+                ShadowOperationType.contains(operation).ifPresent(optional -> 
initShadowAlgorithmNames(optional, each, shadowColumnName, result));
             }
         });
         return result;
     }
     
-    private void initShadowAlgorithmNames(final Map<ShadowOperationType, 
Collection<String>> columnShadowAlgorithmNames, final String algorithmName, 
final ShadowOperationType operationType) {
-        Collection<String> names = 
columnShadowAlgorithmNames.get(operationType);
-        Preconditions.checkState(null == names, "Column shadow algorithm `%s` 
operation only supports one column mapping in shadow table `%s`.", 
operationType.name(), tableName);
-        columnShadowAlgorithmNames.put(operationType, 
Collections.singletonList(algorithmName));
+    private void initShadowAlgorithmNames(final ShadowOperationType 
operationType, final String algorithmName, final String shadowColumnName,
+                                          final Map<ShadowOperationType, 
Collection<ShadowAlgorithmNameRule>> columnShadowAlgorithmNames) {
+        Collection<ShadowAlgorithmNameRule> shadowAlgorithmNameRules = 
columnShadowAlgorithmNames.get(operationType);
+        Preconditions.checkState(null == shadowAlgorithmNameRules, "Column 
shadow algorithm `%s` operation only supports one column mapping in shadow 
table `%s`.", operationType.name(), tableName);
+        columnShadowAlgorithmNames.put(operationType, 
Collections.singletonList(new ShadowAlgorithmNameRule(shadowColumnName, 
algorithmName)));
     }
 }

Reply via email to