You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2020/09/10 10:02:54 UTC

[shardingsphere] branch master updated: Support multi replica extension (#7355)

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 cca800a  Support multi replica extension (#7355)
cca800a is described below

commit cca800aece30251bf630da1a8910ae9cdd231ba3
Author: AlphaPo <ju...@163.com>
AuthorDate: Thu Sep 10 18:02:38 2020 +0800

    Support multi replica extension (#7355)
    
    * Support multi replica extension
    
    * merge from apache/master
    
    * add a blank line in the end of RawExecutorCallback's SPI META-INF file
    rename primaryKeyColumns as result for return value in ExecutionContextBuilder
    use a object to define Map<String, List<String>> structure for primaryKeyColumns
    
    * refactor SQLUnit, add SQLRuntimeContext
    
    * merge from master
    
    Co-authored-by: yanjiabao <ya...@jd.com>
---
 pom.xml                                            |   2 +
 .../EncryptSQLRewriterParameterizedTest.java       |   2 +-
 .../route/engine/MasterSlaveRouteDecorator.java    |   3 +-
 ...va => ReplicaActualTableRuleConfiguration.java} |  28 +++--
 ...ava => ReplicaLogicTableRuleConfiguration.java} |  23 ++--
 .../api/config/ReplicaRuleConfiguration.java       |  13 +-
 .../replica/constant/ReplicaOrder.java             |   2 +-
 .../shardingsphere/replica/rule/ReplicaRule.java   |  75 +++++------
 .../replica/rule/ReplicaTableRule.java             |  38 +++---
 ...> YamlReplicaActualTableRuleConfiguration.java} |  15 +--
 ...=> YamlReplicaLogicTableRuleConfiguration.java} |  10 +-
 .../yaml/config/YamlReplicaRuleConfiguration.java  |   9 +-
 ...icaActualTableRuleConfigurationYamlSwapper.java |  44 +++++++
 ...licaLogicTableRuleConfigurationYamlSwapper.java |  54 ++++++++
 .../ReplicaRuleConfigurationYamlSwapper.java       |  36 ++----
 .../replica/rule/ReplicaRuleTest.java              |  74 +++++++++++
 ...ctualTableRuleConfigurationYamlSwapperTest.java |  72 +++++++++++
 .../ReplicaRuleConfigurationYamlSwapperTest.java   | 138 +++++++++++++--------
 .../shardingsphere-replica-execute/pom.xml         |   5 +
 .../callback/DefaultReplicaExecutorCallback.java   |  54 ++++++++
 .../execute/callback/ReplicaExecutorCallback.java  |  27 ++--
 .../group/ReplicaExecuteGroupDecorator.java        |  83 ++++++++++---
 ...or.sql.raw.execute.callback.RawExecutorCallback |  18 +++
 .../replica/route/engine/ReplicaGroup.java         |  24 ++--
 .../route/engine/ReplicaRouteDecorator.java        |  60 +++++----
 .../route/engine/ReplicaRouteStageContext.java     |  16 +--
 .../shadow/route/engine/ShadowRouteDecorator.java  |   6 +-
 .../MixSQLRewriterParameterizedTest.java           |   4 +-
 .../ShardingSQLRewriterParameterizedTest.java      |   2 +-
 .../route/engine/ShardingRouteDecorator.java       |   3 +-
 .../engine/type/standard/AbstractSQLRouteTest.java |   2 +-
 .../context/schema/GovernanceSchemaContexts.java   |  10 +-
 .../infra/metadata/ShardingSphereMetaData.java     |   2 +
 .../AbstractMetaDataRefreshStrategyTest.java       |   3 +-
 .../infra/context/SchemaContextsBuilder.java       |   2 +-
 .../executor/sql/context/ExecutionContext.java     |   7 +-
 .../sql/context/ExecutionContextBuilder.java       |  84 ++++++++++++-
 .../{SQLUnit.java => PrimaryKeyMetaData.java}      |  10 +-
 .../{SQLUnit.java => SQLRuntimeContext.java}       |  19 ++-
 .../infra/executor/sql/context/SQLUnit.java        |   7 ++
 .../sql/group/AbstractExecuteGroupEngine.java      |   9 +-
 .../executor/sql/group/ExecuteGroupDecorator.java  |   4 +-
 .../executor/sql/group/ExecuteGroupEngine.java     |   4 +-
 .../infra/executor/sql/raw/RawSQLExecuteUnit.java  |   5 +
 ...cutorCallback.java => RawExecutorCallback.java} |  27 ++--
 .../execute/callback/RawSQLExecutorCallback.java   |  25 +++-
 .../sql/raw/group/RawExecuteGroupDecorator.java    |  20 ++-
 .../group/ResourceManagedExecuteGroupEngine.java   |   2 +-
 .../jdbc/group/StatementExecuteGroupEngine.java    |   2 +-
 .../sql/context/ExecutionContextBuilderTest.java   |  35 +++++-
 .../PreparedStatementExecuteGroupEngineTest.java   |   5 +-
 .../group/StatementExecuteGroupEngineTest.java     |   5 +-
 .../infra/executor/sql/log/SQLLoggerTest.java      |   8 +-
 .../infra/rewrite/SQLRewriteEntry.java             |   5 +-
 .../route/context/DefaultRouteStageContext.java    |  15 +--
 .../infra/route/context/RawGroup.java              |  15 +--
 .../infra/route/context/RouteContext.java          |  40 ++++++
 .../infra/route/context/RouteStageContext.java     |  15 +--
 .../fixture/decorator/RouteDecoratorFixture.java   |   3 +-
 .../statement/ShardingSpherePreparedStatement.java |  26 ++--
 .../core/statement/ShardingSphereStatement.java    |  22 ++--
 .../executor/PreparedStatementExecutorTest.java    |   4 +-
 .../driver/executor/StatementExecutorTest.java     |   3 +-
 .../executor/batch/BatchExecutionUnitTest.java     |   7 +-
 .../batch/BatchPreparedStatementExecutorTest.java  |   3 +-
 .../execute/engine/jdbc/JDBCExecuteEngine.java     |  14 ++-
 .../wrapper/PreparedStatementExecutorWrapper.java  |  16 ++-
 .../jdbc/wrapper/StatementExecutorWrapper.java     |  10 +-
 .../hint/ShardingCTLHintBackendHandlerTest.java    |   3 +-
 .../binder/statement/SQLStatementContext.java      |  10 ++
 .../sql/parser/sql/common/util/SQLUtil.java        | 105 ++++++++++++++++
 71 files changed, 1141 insertions(+), 412 deletions(-)

diff --git a/pom.xml b/pom.xml
index 2b9957b..cf0523f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -800,9 +800,11 @@
                 <version>${apache-rat-plugin.version}</version>
                 <configuration>
                     <excludes>
+                        <exclude>**/gen/**</exclude>
                         <exclude>**/target/**</exclude>
                         <exclude>**/logs/**</exclude>
                         <exclude>**/*.log</exclude>
+                        <exclude>**/*.tokens</exclude>
                         <!-- IDE files -->
                         <exclude>**/*.iml</exclude>
                         <exclude>**/.idea/**</exclude>
diff --git a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/test/java/org/apache/shardingsphere/encrypt/rewrite/parameterized/EncryptSQLRewriterParameterizedTest.java b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/test/java/org/apache/shardingsphere/encrypt/rewrite/parameterized/EncryptSQLRewriterParameterizedTest.java
index 2184bee..9d0910b 100644
--- a/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/test/java/org/apache/shardingsphere/encrypt/rewrite/parameterized/EncryptSQLRewriterParameterizedTest.java
+++ b/shardingsphere-features/shardingsphere-encrypt/shardingsphere-encrypt-rewrite/src/test/java/org/apache/shardingsphere/encrypt/rewrite/parameterized/EncryptSQLRewriterParameterizedTest.java
@@ -94,6 +94,6 @@ public final class EncryptSQLRewriterParameterizedTest extends AbstractSQLRewrit
         RuleSchemaMetaData ruleSchemaMetaData = mock(RuleSchemaMetaData.class);
         when(ruleSchemaMetaData.getConfiguredSchemaMetaData()).thenReturn(schemaMetaData);
         when(ruleSchemaMetaData.getSchemaMetaData()).thenReturn(schemaMetaData);
-        return new ShardingSphereMetaData(mock(DataSourceMetaDatas.class), ruleSchemaMetaData);
+        return new ShardingSphereMetaData(mock(DataSourceMetaDatas.class), ruleSchemaMetaData, "sharding_db");
     }
 }
diff --git a/shardingsphere-features/shardingsphere-master-slave/shardingsphere-master-slave-route/src/main/java/org/apache/shardingsphere/masterslave/route/engine/MasterSlaveRouteDecorator.java b/shardingsphere-features/shardingsphere-master-slave/shardingsphere-master-slave-route/src/main/java/org/apache/shardingsphere/masterslave/route/engine/MasterSlaveRouteDecorator.java
index e932087..24f67ba 100644
--- a/shardingsphere-features/shardingsphere-master-slave/shardingsphere-master-slave-route/src/main/java/org/apache/shardingsphere/masterslave/route/engine/MasterSlaveRouteDecorator.java
+++ b/shardingsphere-features/shardingsphere-master-slave/shardingsphere-master-slave-route/src/main/java/org/apache/shardingsphere/masterslave/route/engine/MasterSlaveRouteDecorator.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.masterslave.route.engine;
 import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties;
 import org.apache.shardingsphere.infra.database.DefaultSchema;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import org.apache.shardingsphere.infra.route.context.DefaultRouteStageContext;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.route.context.RouteMapper;
 import org.apache.shardingsphere.infra.route.context.RouteResult;
@@ -46,7 +47,7 @@ public final class MasterSlaveRouteDecorator implements RouteDecorator<MasterSla
             String dataSourceName = new MasterSlaveDataSourceRouter(masterSlaveRule.getSingleDataSourceRule()).route(routeContext.getSqlStatementContext().getSqlStatement());
             RouteResult routeResult = new RouteResult();
             routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(DefaultSchema.LOGIC_NAME, dataSourceName), Collections.emptyList()));
-            return new RouteContext(routeContext.getSqlStatementContext(), routeContext.getParameters(), routeResult);
+            return new RouteContext(routeContext, routeResult, new DefaultRouteStageContext(), getTypeClass());
         }
         Collection<RouteUnit> toBeRemoved = new LinkedList<>();
         Collection<RouteUnit> toBeAdded = new LinkedList<>();
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaDataSourceConfiguration.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaActualTableRuleConfiguration.java
similarity index 50%
copy from shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaDataSourceConfiguration.java
copy to shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaActualTableRuleConfiguration.java
index 4ab9920..3c62c18 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaDataSourceConfiguration.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaActualTableRuleConfiguration.java
@@ -22,22 +22,28 @@ import com.google.common.base.Strings;
 import lombok.Getter;
 import org.apache.shardingsphere.infra.config.RuleConfiguration;
 
-import java.util.Collection;
-
 /**
- * Replica data source configuration.
+ * Replica actual table rule configuration.
  */
 @Getter
-public final class ReplicaDataSourceConfiguration implements RuleConfiguration {
+public final class ReplicaActualTableRuleConfiguration implements RuleConfiguration {
+    
+    private final String physicsTable;
+    
+    private final String replicaGroupId;
     
-    private final String name;
+    private final String replicaPeers;
     
-    private final Collection<String> replicaSourceNames;
+    private final String dataSourceName;
     
-    public ReplicaDataSourceConfiguration(final String name, final Collection<String> replicaSourceNames) {
-        Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "Name is required.");
-        Preconditions.checkArgument(null != replicaSourceNames && !replicaSourceNames.isEmpty(), "replica source names are required.");
-        this.name = name;
-        this.replicaSourceNames = replicaSourceNames;
+    public ReplicaActualTableRuleConfiguration(final String physicsTable, final String replicaGroupId, final String replicaPeers, final String dataSourceName) {
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(physicsTable), "physicsTable is required.");
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(replicaGroupId), "replicaGroupId is required.");
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(replicaPeers), "replicaPeers is required.");
+        Preconditions.checkArgument(!Strings.isNullOrEmpty(dataSourceName), "dataSourceName is required.");
+        this.physicsTable = physicsTable;
+        this.replicaGroupId = replicaGroupId;
+        this.replicaPeers = replicaPeers;
+        this.dataSourceName = dataSourceName;
     }
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaDataSourceConfiguration.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaLogicTableRuleConfiguration.java
similarity index 59%
rename from shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaDataSourceConfiguration.java
rename to shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaLogicTableRuleConfiguration.java
index 4ab9920..97798ac 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaDataSourceConfiguration.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaLogicTableRuleConfiguration.java
@@ -17,27 +17,28 @@
 
 package org.apache.shardingsphere.replica.api.config;
 
-import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
 import lombok.Getter;
 import org.apache.shardingsphere.infra.config.RuleConfiguration;
 
 import java.util.Collection;
+import java.util.Collections;
 
 /**
- * Replica data source configuration.
+ * Replica logic table rule configuration.
  */
 @Getter
-public final class ReplicaDataSourceConfiguration implements RuleConfiguration {
+public final class ReplicaLogicTableRuleConfiguration implements RuleConfiguration {
     
-    private final String name;
+    private final String logicTable;
     
-    private final Collection<String> replicaSourceNames;
+    private final Collection<ReplicaActualTableRuleConfiguration> replicaGroups;
     
-    public ReplicaDataSourceConfiguration(final String name, final Collection<String> replicaSourceNames) {
-        Preconditions.checkArgument(!Strings.isNullOrEmpty(name), "Name is required.");
-        Preconditions.checkArgument(null != replicaSourceNames && !replicaSourceNames.isEmpty(), "replica source names are required.");
-        this.name = name;
-        this.replicaSourceNames = replicaSourceNames;
+    public ReplicaLogicTableRuleConfiguration(final String logicTable, final Collection<ReplicaActualTableRuleConfiguration> replicaGroups) {
+        this.logicTable = logicTable;
+        if (null != replicaGroups) {
+            this.replicaGroups = replicaGroups;
+        } else {
+            this.replicaGroups = Collections.emptyList();
+        }
     }
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaRuleConfiguration.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaRuleConfiguration.java
index 6149a0a..fa236b9 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaRuleConfiguration.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaRuleConfiguration.java
@@ -18,17 +18,24 @@
 package org.apache.shardingsphere.replica.api.config;
 
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
 import org.apache.shardingsphere.infra.config.RuleConfiguration;
 
 import java.util.Collection;
+import java.util.Collections;
 
 /**
  * Replica rule configuration.
  */
-@RequiredArgsConstructor
 @Getter
 public final class ReplicaRuleConfiguration implements RuleConfiguration {
     
-    private final Collection<ReplicaDataSourceConfiguration> dataSources;
+    private final Collection<ReplicaLogicTableRuleConfiguration> tables;
+    
+    public ReplicaRuleConfiguration(final Collection<ReplicaLogicTableRuleConfiguration> tables) {
+        if (null != tables) {
+            this.tables = tables;
+        } else {
+            this.tables = Collections.emptyList();
+        }
+    }
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java
index 2f4efab..2dff541 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java
@@ -29,5 +29,5 @@ public final class ReplicaOrder {
     /**
      * Replica order.
      */
-    public static final int ORDER = 20;
+    public static final int ORDER = 80;
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/rule/ReplicaRule.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/rule/ReplicaRule.java
index 9098166..a76ae2c 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/rule/ReplicaRule.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/rule/ReplicaRule.java
@@ -17,66 +17,55 @@
 
 package org.apache.shardingsphere.replica.rule;
 
-import org.apache.shardingsphere.infra.rule.DataSourceRoutedRule;
-import org.apache.shardingsphere.replica.api.config.ReplicaDataSourceConfiguration;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+import org.apache.shardingsphere.replica.api.config.ReplicaActualTableRuleConfiguration;
+import org.apache.shardingsphere.replica.api.config.ReplicaLogicTableRuleConfiguration;
 import org.apache.shardingsphere.replica.api.config.ReplicaRuleConfiguration;
 
+import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Replica rule.
  */
-public final class ReplicaRule implements DataSourceRoutedRule {
+@Slf4j
+public final class ReplicaRule implements ShardingSphereRule {
     
-    private final Map<String, Collection<String>> dataSourceRules;
+    @Getter
+    private final Collection<ReplicaTableRule> replicaTableRules;
+    
+    private final Map<String, ReplicaTableRule> physicsTableRules;
     
     public ReplicaRule(final ReplicaRuleConfiguration configuration) {
-        dataSourceRules = new HashMap<>(configuration.getDataSources().size(), 1);
-        for (ReplicaDataSourceConfiguration each : configuration.getDataSources()) {
-            dataSourceRules.put(each.getName(), each.getReplicaSourceNames());
+        Collection<ReplicaTableRule> replicaTableRules = new ArrayList<>();
+        Map<String, ReplicaTableRule> physicsTableRules = new ConcurrentHashMap<>();
+        for (ReplicaLogicTableRuleConfiguration entry : configuration.getTables()) {
+            for (ReplicaActualTableRuleConfiguration each : entry.getReplicaGroups()) {
+                String physicsTable = each.getPhysicsTable();
+                ReplicaTableRule replaced = physicsTableRules.putIfAbsent(physicsTable, new ReplicaTableRule(each));
+                if (null != replaced) {
+                    log.error("key already exists, key={}", physicsTable);
+                    throw new IllegalArgumentException("key already exists, key=" + physicsTable);
+                }
+                replicaTableRules.add(new ReplicaTableRule(each));
+            }
         }
+        this.replicaTableRules = replicaTableRules;
+        this.physicsTableRules = physicsTableRules;
     }
     
     /**
-     * Get single replica data sources.
+     * Find routing by table.
      *
-     * @return replica data source rule
-     */
-    public Collection<String> getSingleReplicaDataSources() {
-        return dataSourceRules.values().iterator().next();
-    }
-    
-    /**
-     * Find replica data sources.
-     * 
-     * @param dataSourceName data source name
-     * @return replica data source names
-     */
-    public Optional<Collection<String>> findReplicaDataSources(final String dataSourceName) {
-        return Optional.ofNullable(dataSourceRules.get(dataSourceName));
-    }
-    
-    /**
-     * Find logic data source name.
-     * 
-     * @param replicaDataSourceName replica data source name
-     * @return logic data source name
+     * @param physicsTable physics table name
+     * @return replica table rule
      */
-    public Optional<String> findLogicDataSource(final String replicaDataSourceName) {
-        for (Entry<String, Collection<String>> entry : dataSourceRules.entrySet()) {
-            if (entry.getValue().contains(replicaDataSourceName)) {
-                return Optional.of(entry.getKey());
-            }
-        }
-        return Optional.empty();
-    }
-    
-    @Override
-    public Map<String, Collection<String>> getDataSourceMapper() {
-        return dataSourceRules;
+    public Optional<ReplicaTableRule> findRoutingByTable(final String physicsTable) {
+        return Optional.ofNullable(physicsTableRules.get(physicsTable));
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupDecorator.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/rule/ReplicaTableRule.java
similarity index 53%
copy from shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupDecorator.java
copy to shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/rule/ReplicaTableRule.java
index 4568465..56cd2c2 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupDecorator.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/rule/ReplicaTableRule.java
@@ -15,28 +15,30 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.executor.sql.group;
+package org.apache.shardingsphere.replica.rule;
 
+import lombok.Getter;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
-import org.apache.shardingsphere.infra.spi.order.OrderedSPI;
-import org.apache.shardingsphere.infra.executor.kernel.InputGroup;
-
-import java.util.Collection;
+import org.apache.shardingsphere.replica.api.config.ReplicaActualTableRuleConfiguration;
 
 /**
- * Execute group decorator.
- * 
- * @param <T> type of input value
- * @param <R> type of ShardingSphere rule
+ * Replica table rule.
  */
-public interface ExecuteGroupDecorator<T, R extends ShardingSphereRule> extends OrderedSPI<R> {
+@Getter
+public final class ReplicaTableRule implements ShardingSphereRule {
+    
+    private final String physicsTable;
+    
+    private final String replicaGroupId;
+    
+    private final String replicaPeers;
+    
+    private final String dataSourceName;
     
-    /**
-     * Decorate input groups.
-     * 
-     * @param rule ShardingSphere rule
-     * @param inputGroups input groups to be decorated
-     * @return decorated input groups.
-     */
-    Collection<InputGroup<T>> decorate(R rule, Collection<InputGroup<T>> inputGroups);
+    public ReplicaTableRule(final ReplicaActualTableRuleConfiguration configuration) {
+        physicsTable = configuration.getPhysicsTable();
+        replicaGroupId = configuration.getReplicaGroupId();
+        replicaPeers = configuration.getReplicaPeers();
+        dataSourceName = configuration.getDataSourceName();
+    }
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaDataSourceConfiguration.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaActualTableRuleConfiguration.java
similarity index 77%
copy from shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaDataSourceConfiguration.java
copy to shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaActualTableRuleConfiguration.java
index cf4d512..91e5614 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaDataSourceConfiguration.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaActualTableRuleConfiguration.java
@@ -21,17 +21,18 @@ import lombok.Getter;
 import lombok.Setter;
 import org.apache.shardingsphere.infra.yaml.config.YamlConfiguration;
 
-import java.util.Collection;
-import java.util.LinkedList;
-
 /**
- * Replica data source configuration for YAML.
+ * Replica actual table rule configuration for YAML.
  */
 @Getter
 @Setter
-public final class YamlReplicaDataSourceConfiguration implements YamlConfiguration {
+public final class YamlReplicaActualTableRuleConfiguration implements YamlConfiguration {
+    
+    private String physicsTable;
+    
+    private String replicaGroupId;
     
-    private String name;
+    private String replicaPeers;
     
-    private Collection<String> replicaDataSourceNames = new LinkedList<>();
+    private String dataSourceName;
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaDataSourceConfiguration.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaLogicTableRuleConfiguration.java
similarity index 77%
rename from shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaDataSourceConfiguration.java
rename to shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaLogicTableRuleConfiguration.java
index cf4d512..ccbc656 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaDataSourceConfiguration.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaLogicTableRuleConfiguration.java
@@ -22,16 +22,16 @@ import lombok.Setter;
 import org.apache.shardingsphere.infra.yaml.config.YamlConfiguration;
 
 import java.util.Collection;
-import java.util.LinkedList;
+import java.util.Collections;
 
 /**
- * Replica data source configuration for YAML.
+ * Replica logic table rule configuration for YAML.
  */
 @Getter
 @Setter
-public final class YamlReplicaDataSourceConfiguration implements YamlConfiguration {
+public final class YamlReplicaLogicTableRuleConfiguration implements YamlConfiguration {
     
-    private String name;
+    private String logicTable;
     
-    private Collection<String> replicaDataSourceNames = new LinkedList<>();
+    private Collection<YamlReplicaActualTableRuleConfiguration> replicaGroups = Collections.emptyList();
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaRuleConfiguration.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaRuleConfiguration.java
index 10e3113..4d29916 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaRuleConfiguration.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/config/YamlReplicaRuleConfiguration.java
@@ -19,11 +19,12 @@ package org.apache.shardingsphere.replica.yaml.config;
 
 import lombok.Getter;
 import lombok.Setter;
+import org.apache.shardingsphere.infra.config.RuleConfiguration;
 import org.apache.shardingsphere.infra.yaml.config.YamlRuleConfiguration;
 import org.apache.shardingsphere.replica.api.config.ReplicaRuleConfiguration;
 
-import java.util.LinkedHashMap;
-import java.util.Map;
+import java.util.Collection;
+import java.util.Collections;
 
 /**
  * Replica rule configuration for YAML.
@@ -32,10 +33,10 @@ import java.util.Map;
 @Setter
 public final class YamlReplicaRuleConfiguration implements YamlRuleConfiguration {
     
-    private Map<String, YamlReplicaDataSourceConfiguration> dataSources = new LinkedHashMap<>();
+    private Collection<YamlReplicaLogicTableRuleConfiguration> tables = Collections.emptyList();
     
     @Override
-    public Class<ReplicaRuleConfiguration> getRuleConfigurationType() {
+    public Class<? extends RuleConfiguration> getRuleConfigurationType() {
         return ReplicaRuleConfiguration.class;
     }
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaActualTableRuleConfigurationYamlSwapper.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaActualTableRuleConfigurationYamlSwapper.java
new file mode 100644
index 0000000..d3ff571
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaActualTableRuleConfigurationYamlSwapper.java
@@ -0,0 +1,44 @@
+/*
+ * 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.replica.yaml.swapper;
+
+import org.apache.shardingsphere.infra.yaml.swapper.YamlSwapper;
+import org.apache.shardingsphere.replica.api.config.ReplicaActualTableRuleConfiguration;
+import org.apache.shardingsphere.replica.yaml.config.YamlReplicaActualTableRuleConfiguration;
+
+/**
+ * Replica actual table rule configuration YAML swapper.
+ */
+public final class ReplicaActualTableRuleConfigurationYamlSwapper implements YamlSwapper<YamlReplicaActualTableRuleConfiguration, ReplicaActualTableRuleConfiguration> {
+    
+    @Override
+    public YamlReplicaActualTableRuleConfiguration swapToYamlConfiguration(final ReplicaActualTableRuleConfiguration data) {
+        YamlReplicaActualTableRuleConfiguration result = new YamlReplicaActualTableRuleConfiguration();
+        result.setPhysicsTable(data.getPhysicsTable());
+        result.setReplicaGroupId(data.getReplicaGroupId());
+        result.setReplicaPeers(data.getReplicaPeers());
+        result.setDataSourceName(data.getDataSourceName());
+        return result;
+    }
+    
+    @Override
+    public ReplicaActualTableRuleConfiguration swapToObject(final YamlReplicaActualTableRuleConfiguration yamlConfiguration) {
+        return new ReplicaActualTableRuleConfiguration(yamlConfiguration.getPhysicsTable(), yamlConfiguration.getReplicaGroupId(),
+                yamlConfiguration.getReplicaPeers(), yamlConfiguration.getDataSourceName());
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaLogicTableRuleConfigurationYamlSwapper.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaLogicTableRuleConfigurationYamlSwapper.java
new file mode 100644
index 0000000..71bd7a0
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaLogicTableRuleConfigurationYamlSwapper.java
@@ -0,0 +1,54 @@
+/*
+ * 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.replica.yaml.swapper;
+
+import org.apache.shardingsphere.infra.yaml.swapper.YamlSwapper;
+import org.apache.shardingsphere.replica.api.config.ReplicaActualTableRuleConfiguration;
+import org.apache.shardingsphere.replica.api.config.ReplicaLogicTableRuleConfiguration;
+import org.apache.shardingsphere.replica.yaml.config.YamlReplicaActualTableRuleConfiguration;
+import org.apache.shardingsphere.replica.yaml.config.YamlReplicaLogicTableRuleConfiguration;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+/**
+ * Replica logic table rule configuration YAML swapper.
+ */
+public final class ReplicaLogicTableRuleConfigurationYamlSwapper implements YamlSwapper<YamlReplicaLogicTableRuleConfiguration, ReplicaLogicTableRuleConfiguration> {
+    
+    private final ReplicaActualTableRuleConfigurationYamlSwapper actualTableRuleConfigurationYamlSwapper = new ReplicaActualTableRuleConfigurationYamlSwapper();
+    
+    @Override
+    public YamlReplicaLogicTableRuleConfiguration swapToYamlConfiguration(final ReplicaLogicTableRuleConfiguration data) {
+        Collection<YamlReplicaActualTableRuleConfiguration> replicaGroups = data.getReplicaGroups().stream()
+                .map(actualTableRuleConfigurationYamlSwapper::swapToYamlConfiguration)
+                .collect(Collectors.toList());
+        YamlReplicaLogicTableRuleConfiguration result = new YamlReplicaLogicTableRuleConfiguration();
+        result.setLogicTable(data.getLogicTable());
+        result.setReplicaGroups(replicaGroups);
+        return result;
+    }
+    
+    @Override
+    public ReplicaLogicTableRuleConfiguration swapToObject(final YamlReplicaLogicTableRuleConfiguration yamlConfiguration) {
+        Collection<ReplicaActualTableRuleConfiguration> replicaGroups = yamlConfiguration.getReplicaGroups().stream()
+                .map(actualTableRuleConfigurationYamlSwapper::swapToObject)
+                .collect(Collectors.toList());
+        return new ReplicaLogicTableRuleConfiguration(yamlConfiguration.getLogicTable(), replicaGroups);
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaRuleConfigurationYamlSwapper.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaRuleConfigurationYamlSwapper.java
index d51e36c..18fa86b 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaRuleConfigurationYamlSwapper.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaRuleConfigurationYamlSwapper.java
@@ -18,16 +18,13 @@
 package org.apache.shardingsphere.replica.yaml.swapper;
 
 import org.apache.shardingsphere.infra.yaml.swapper.YamlRuleConfigurationSwapper;
-import org.apache.shardingsphere.replica.api.config.ReplicaDataSourceConfiguration;
+import org.apache.shardingsphere.replica.api.config.ReplicaLogicTableRuleConfiguration;
 import org.apache.shardingsphere.replica.api.config.ReplicaRuleConfiguration;
 import org.apache.shardingsphere.replica.constant.ReplicaOrder;
-import org.apache.shardingsphere.replica.yaml.config.YamlReplicaDataSourceConfiguration;
+import org.apache.shardingsphere.replica.yaml.config.YamlReplicaLogicTableRuleConfiguration;
 import org.apache.shardingsphere.replica.yaml.config.YamlReplicaRuleConfiguration;
 
 import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.Map.Entry;
 import java.util.stream.Collectors;
 
 /**
@@ -35,31 +32,24 @@ import java.util.stream.Collectors;
  */
 public final class ReplicaRuleConfigurationYamlSwapper implements YamlRuleConfigurationSwapper<YamlReplicaRuleConfiguration, ReplicaRuleConfiguration> {
     
+    private final ReplicaLogicTableRuleConfigurationYamlSwapper logicTableRuleConfigurationYamlSwapper = new ReplicaLogicTableRuleConfigurationYamlSwapper();
+    
     @Override
     public YamlReplicaRuleConfiguration swapToYamlConfiguration(final ReplicaRuleConfiguration data) {
+        Collection<YamlReplicaLogicTableRuleConfiguration> yamlTables = data.getTables().stream()
+                .map(logicTableRuleConfigurationYamlSwapper::swapToYamlConfiguration)
+                .collect(Collectors.toList());
         YamlReplicaRuleConfiguration result = new YamlReplicaRuleConfiguration();
-        result.setDataSources(data.getDataSources().stream().collect(Collectors.toMap(ReplicaDataSourceConfiguration::getName, this::swapToYamlConfiguration, (a, b) -> b, LinkedHashMap::new)));
-        return result;
-    }
-    
-    private YamlReplicaDataSourceConfiguration swapToYamlConfiguration(final ReplicaDataSourceConfiguration group) {
-        YamlReplicaDataSourceConfiguration result = new YamlReplicaDataSourceConfiguration();
-        result.setName(group.getName());
-        result.setReplicaDataSourceNames(group.getReplicaSourceNames());
+        result.setTables(yamlTables);
         return result;
     }
     
     @Override
-    public ReplicaRuleConfiguration swapToObject(final YamlReplicaRuleConfiguration yamlConfig) {
-        Collection<ReplicaDataSourceConfiguration> groups = new LinkedList<>();
-        for (Entry<String, YamlReplicaDataSourceConfiguration> entry : yamlConfig.getDataSources().entrySet()) {
-            groups.add(swapToObject(entry.getKey(), entry.getValue()));
-        }
-        return new ReplicaRuleConfiguration(groups);
-    }
-    
-    private ReplicaDataSourceConfiguration swapToObject(final String name, final YamlReplicaDataSourceConfiguration yamlGroup) {
-        return new ReplicaDataSourceConfiguration(name, yamlGroup.getReplicaDataSourceNames());
+    public ReplicaRuleConfiguration swapToObject(final YamlReplicaRuleConfiguration yamlConfiguration) {
+        Collection<ReplicaLogicTableRuleConfiguration> tables = yamlConfiguration.getTables().stream()
+                .map(logicTableRuleConfigurationYamlSwapper::swapToObject)
+                .collect(Collectors.toList());
+        return new ReplicaRuleConfiguration(tables);
     }
     
     @Override
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/rule/ReplicaRuleTest.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/rule/ReplicaRuleTest.java
new file mode 100644
index 0000000..be19f3e
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/rule/ReplicaRuleTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.replica.rule;
+
+import org.apache.shardingsphere.replica.api.config.ReplicaActualTableRuleConfiguration;
+import org.apache.shardingsphere.replica.api.config.ReplicaLogicTableRuleConfiguration;
+import org.apache.shardingsphere.replica.api.config.ReplicaRuleConfiguration;
+import org.junit.Test;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public final class ReplicaRuleTest {
+    
+    private final String logicTableName = "t_order";
+    
+    private final String dataSourceName = "demo_ds_0";
+    
+    private final String physicsTable = "t_order_1";
+    
+    private final String replicaGroupId = "raftGroupTest1";
+    
+    private final String replicaPeers = "127.0.0.1:9090";
+    
+    private ReplicaRule createReplicaRule() {
+        ReplicaActualTableRuleConfiguration replicaGroup = new ReplicaActualTableRuleConfiguration(physicsTable, replicaGroupId, replicaPeers, dataSourceName);
+        Collection<ReplicaActualTableRuleConfiguration> replicaGroups = Collections.singleton(replicaGroup);
+        ReplicaLogicTableRuleConfiguration table = new ReplicaLogicTableRuleConfiguration(logicTableName, replicaGroups);
+        ReplicaRuleConfiguration configuration = new ReplicaRuleConfiguration(Collections.singleton(table));
+        return new ReplicaRule(configuration);
+    }
+    
+    @Test
+    public void assertCannotFindRouting() {
+        ReplicaRule replicaRule = createReplicaRule();
+        Optional<ReplicaTableRule> routingRuleOptional = replicaRule.findRoutingByTable("not_exists_table");
+        assertFalse(routingRuleOptional.isPresent());
+    }
+    
+    @Test
+    public void assertRoutingFound() {
+        ReplicaRule replicaRule = createReplicaRule();
+        Optional<ReplicaTableRule> routingRuleOptional = replicaRule.findRoutingByTable(physicsTable);
+        assertTrue(routingRuleOptional.isPresent());
+        ReplicaTableRule routingRule = routingRuleOptional.get();
+        assertNotNull(routingRule);
+        assertThat(routingRule.getDataSourceName(), is(dataSourceName));
+        assertThat(routingRule.getPhysicsTable(), is(physicsTable));
+        assertThat(routingRule.getReplicaGroupId(), is(replicaGroupId));
+        assertThat(routingRule.getReplicaPeers(), is(replicaPeers));
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaActualTableRuleConfigurationYamlSwapperTest.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaActualTableRuleConfigurationYamlSwapperTest.java
new file mode 100644
index 0000000..66cffd4
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaActualTableRuleConfigurationYamlSwapperTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.replica.yaml.swapper;
+
+import org.apache.shardingsphere.replica.api.config.ReplicaActualTableRuleConfiguration;
+import org.apache.shardingsphere.replica.yaml.config.YamlReplicaActualTableRuleConfiguration;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ReplicaActualTableRuleConfigurationYamlSwapperTest {
+    
+    private final ReplicaActualTableRuleConfigurationYamlSwapper swapper = new ReplicaActualTableRuleConfigurationYamlSwapper();
+    
+    private final String dataSourceName = "demo_ds_0";
+    
+    private final String physicsTable = "t_order_1";
+    
+    private final String replicaGroupId = "raftGroupTest1";
+    
+    private final String replicaPeers = "127.0.0.1:9090";
+    
+    @Test(expected = IllegalArgumentException.class)
+    public void assertSwapToYamlConfigurationWithMinProperties() {
+        swapper.swapToYamlConfiguration(new ReplicaActualTableRuleConfiguration(null, null, null, null));
+    }
+    
+    @Test
+    public void assertSwapToYamlConfigurationWithMaxProperties() {
+        YamlReplicaActualTableRuleConfiguration yamlConfiguration = swapper.swapToYamlConfiguration(
+                new ReplicaActualTableRuleConfiguration(physicsTable, replicaGroupId, replicaPeers, dataSourceName));
+        assertThat(yamlConfiguration.getDataSourceName(), is(dataSourceName));
+        assertThat(yamlConfiguration.getPhysicsTable(), is(physicsTable));
+        assertThat(yamlConfiguration.getReplicaGroupId(), is(replicaGroupId));
+        assertThat(yamlConfiguration.getReplicaPeers(), is(replicaPeers));
+    }
+    
+    @Test(expected = IllegalArgumentException.class)
+    public void assertSwapToObjectWithMinProperties() {
+        new ReplicaActualTableRuleConfiguration(null, null, null, null);
+    }
+    
+    @Test
+    public void assertSwapToObjectWithMaxProperties() {
+        YamlReplicaActualTableRuleConfiguration yamlConfiguration = new YamlReplicaActualTableRuleConfiguration();
+        yamlConfiguration.setPhysicsTable(physicsTable);
+        yamlConfiguration.setReplicaGroupId(replicaGroupId);
+        yamlConfiguration.setReplicaPeers(replicaPeers);
+        yamlConfiguration.setDataSourceName(dataSourceName);
+        ReplicaActualTableRuleConfiguration configuration = swapper.swapToObject(yamlConfiguration);
+        assertThat(configuration.getDataSourceName(), is(dataSourceName));
+        assertThat(configuration.getPhysicsTable(), is(physicsTable));
+        assertThat(configuration.getReplicaGroupId(), is(replicaGroupId));
+        assertThat(configuration.getReplicaPeers(), is(replicaPeers));
+    }
+}
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaRuleConfigurationYamlSwapperTest.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaRuleConfigurationYamlSwapperTest.java
index abdb50d..e21495e 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaRuleConfigurationYamlSwapperTest.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/test/java/org/apache/shardingsphere/replica/yaml/swapper/ReplicaRuleConfigurationYamlSwapperTest.java
@@ -17,76 +17,106 @@
 
 package org.apache.shardingsphere.replica.yaml.swapper;
 
-import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
-import org.apache.shardingsphere.infra.spi.order.OrderedSPIRegistry;
-import org.apache.shardingsphere.infra.yaml.swapper.YamlRuleConfigurationSwapper;
-import org.apache.shardingsphere.replica.api.config.ReplicaDataSourceConfiguration;
+import org.apache.shardingsphere.replica.api.config.ReplicaActualTableRuleConfiguration;
+import org.apache.shardingsphere.replica.api.config.ReplicaLogicTableRuleConfiguration;
 import org.apache.shardingsphere.replica.api.config.ReplicaRuleConfiguration;
-import org.apache.shardingsphere.replica.yaml.config.YamlReplicaDataSourceConfiguration;
+import org.apache.shardingsphere.replica.yaml.config.YamlReplicaActualTableRuleConfiguration;
+import org.apache.shardingsphere.replica.yaml.config.YamlReplicaLogicTableRuleConfiguration;
 import org.apache.shardingsphere.replica.yaml.config.YamlReplicaRuleConfiguration;
 import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
 
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
 
 import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertNotNull;
 
-@RunWith(MockitoJUnitRunner.class)
 public final class ReplicaRuleConfigurationYamlSwapperTest {
-
-    static {
-        ShardingSphereServiceLoader.register(YamlRuleConfigurationSwapper.class);
-    }
-
-    @Mock
-    private ReplicaRuleConfiguration ruleConfig;
-
+    
+    private final ReplicaRuleConfigurationYamlSwapper swapper = new ReplicaRuleConfigurationYamlSwapper();
+    
+    private final String logicTableName = "t_order";
+    
+    private final String dataSourceName = "demo_ds_0";
+    
+    private final String physicsTable = "t_order_1";
+    
+    private final String replicaGroupId = "raftGroupTest1";
+    
+    private final String replicaPeers = "127.0.0.1:9090";
+    
     @Test
-    public void assertSwapToYamlConfiguration() {
-        YamlReplicaRuleConfiguration configuration = getSwapper().swapToYamlConfiguration(createReplicaRuleConfiguration());
-        assertThat(configuration.getDataSources().size(), is(1));
-        assertTrue(configuration.getDataSources().containsKey("name"));
-        assertTrue(configuration.getDataSources().get("name").getReplicaDataSourceNames().contains("replicaSourceNames"));
+    public void assertSwapToYamlConfigurationWithMinProperties() {
+        YamlReplicaRuleConfiguration yamlConfiguration = swapper.swapToYamlConfiguration(new ReplicaRuleConfiguration(
+                Collections.singleton(new ReplicaLogicTableRuleConfiguration(logicTableName, null))));
+        assertNotNull(yamlConfiguration);
+        assertNotNull(yamlConfiguration.getTables());
+        assertThat(yamlConfiguration.getTables().size(), is(1));
+        Collection<YamlReplicaActualTableRuleConfiguration> resultReplicaGroups = yamlConfiguration.getTables().iterator().next().getReplicaGroups();
+        assertNotNull(resultReplicaGroups);
+        assertTrue(resultReplicaGroups.isEmpty());
     }
-
-    private ReplicaRuleConfiguration createReplicaRuleConfiguration() {
-        ReplicaDataSourceConfiguration configuration = new ReplicaDataSourceConfiguration("name", Arrays.asList("replicaSourceNames"));
-        ReplicaRuleConfiguration replicaRuleConfiguration = new ReplicaRuleConfiguration(Arrays.asList(configuration));
-        return replicaRuleConfiguration;
-    }
-
+    
     @Test
-    public void assertSwapToObject() {
-        ReplicaRuleConfiguration configuration = getSwapper().swapToObject(createYamlReplicaRuleConfiguration());
-        assertThat(configuration.getDataSources().size(), is(1));
-        Collection<ReplicaDataSourceConfiguration> dataSources = configuration.getDataSources();
-        ReplicaDataSourceConfiguration sourceConfiguration = dataSources.stream().findFirst().orElse(null);
-        assertNotNull(sourceConfiguration);
-        assertThat(sourceConfiguration.getName(), is("dataSources"));
-        assertTrue(sourceConfiguration.getReplicaSourceNames().contains("replicaDataSourceNames"));
+    public void assertSwapToYamlConfigurationWithMaxProperties() {
+        ReplicaActualTableRuleConfiguration replicaGroup = new ReplicaActualTableRuleConfiguration(physicsTable, replicaGroupId, replicaPeers, dataSourceName);
+        Collection<ReplicaActualTableRuleConfiguration> replicaGroups = Collections.singleton(replicaGroup);
+        ReplicaLogicTableRuleConfiguration table = new ReplicaLogicTableRuleConfiguration(logicTableName, replicaGroups);
+        YamlReplicaRuleConfiguration yamlConfiguration = swapper.swapToYamlConfiguration(new ReplicaRuleConfiguration(Collections.singleton(table)));
+        assertNotNull(yamlConfiguration);
+        assertNotNull(yamlConfiguration.getTables());
+        assertThat(yamlConfiguration.getTables().size(), is(1));
+        Collection<YamlReplicaActualTableRuleConfiguration> resultReplicaGroups = yamlConfiguration.getTables().iterator().next().getReplicaGroups();
+        assertNotNull(resultReplicaGroups);
+        assertThat(resultReplicaGroups.size(), is(1));
+        YamlReplicaActualTableRuleConfiguration resultReplicaGroup = resultReplicaGroups.iterator().next();
+        assertThat(resultReplicaGroup.getDataSourceName(), is(dataSourceName));
+        assertThat(resultReplicaGroup.getPhysicsTable(), is(physicsTable));
+        assertThat(resultReplicaGroup.getReplicaGroupId(), is(replicaGroupId));
+        assertThat(resultReplicaGroup.getReplicaPeers(), is(replicaPeers));
     }
-
-    private YamlReplicaRuleConfiguration createYamlReplicaRuleConfiguration() {
-        YamlReplicaDataSourceConfiguration configuration = new YamlReplicaDataSourceConfiguration();
-        configuration.setName("name");
-        configuration.setReplicaDataSourceNames(Arrays.asList("replicaDataSourceNames"));
-        Map<String, YamlReplicaDataSourceConfiguration> dataSources = new LinkedHashMap<>();
-        dataSources.put("dataSources", configuration);
-        YamlReplicaRuleConfiguration yamlReplicaRuleConfiguration = new YamlReplicaRuleConfiguration();
-        yamlReplicaRuleConfiguration.setDataSources(dataSources);
-        return yamlReplicaRuleConfiguration;
+    
+    @Test
+    public void assertSwapToObjectWithMinProperties() {
+        YamlReplicaLogicTableRuleConfiguration yamlLogicTable = new YamlReplicaLogicTableRuleConfiguration();
+        yamlLogicTable.setLogicTable(logicTableName);
+        YamlReplicaRuleConfiguration yamlConfiguration = new YamlReplicaRuleConfiguration();
+        yamlConfiguration.setTables(Collections.singleton(yamlLogicTable));
+        ReplicaRuleConfiguration configuration = swapper.swapToObject(yamlConfiguration);
+        assertNotNull(configuration);
+        assertNotNull(configuration.getTables());
+        assertThat(configuration.getTables().size(), is(1));
+        Collection<ReplicaActualTableRuleConfiguration> resultReplicaGroups = configuration.getTables().iterator().next().getReplicaGroups();
+        assertNotNull(resultReplicaGroups);
+        assertTrue(resultReplicaGroups.isEmpty());
     }
-
-    private ReplicaRuleConfigurationYamlSwapper getSwapper() {
-        return (ReplicaRuleConfigurationYamlSwapper) OrderedSPIRegistry.getRegisteredServices(Collections.singletonList(ruleConfig), YamlRuleConfigurationSwapper.class).get(ruleConfig);
+    
+    @Test
+    public void assertSwapToObjectWithMaxProperties() {
+        YamlReplicaActualTableRuleConfiguration replicaGroup = new YamlReplicaActualTableRuleConfiguration();
+        replicaGroup.setPhysicsTable(physicsTable);
+        replicaGroup.setReplicaGroupId(replicaGroupId);
+        replicaGroup.setReplicaPeers(replicaPeers);
+        replicaGroup.setDataSourceName(dataSourceName);
+        Collection<YamlReplicaActualTableRuleConfiguration> replicaGroups = Collections.singleton(replicaGroup);
+        YamlReplicaLogicTableRuleConfiguration table = new YamlReplicaLogicTableRuleConfiguration();
+        table.setLogicTable(logicTableName);
+        table.setReplicaGroups(replicaGroups);
+        YamlReplicaRuleConfiguration yamlConfiguration = new YamlReplicaRuleConfiguration();
+        yamlConfiguration.setTables(Collections.singleton(table));
+        ReplicaRuleConfiguration configuration = swapper.swapToObject(yamlConfiguration);
+        assertNotNull(configuration);
+        assertNotNull(configuration.getTables());
+        assertThat(configuration.getTables().size(), is(1));
+        Collection<ReplicaActualTableRuleConfiguration> resultReplicaGroups = configuration.getTables().iterator().next().getReplicaGroups();
+        assertNotNull(resultReplicaGroups);
+        assertThat(resultReplicaGroups.size(), is(1));
+        ReplicaActualTableRuleConfiguration resultReplicaGroup = resultReplicaGroups.iterator().next();
+        assertThat(resultReplicaGroup.getDataSourceName(), is(dataSourceName));
+        assertThat(resultReplicaGroup.getPhysicsTable(), is(physicsTable));
+        assertThat(resultReplicaGroup.getReplicaGroupId(), is(replicaGroupId));
+        assertThat(resultReplicaGroup.getReplicaPeers(), is(replicaPeers));
     }
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/pom.xml b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/pom.xml
index af86a5a..5c38ad8 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/pom.xml
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/pom.xml
@@ -36,6 +36,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.shardingsphere</groupId>
+            <artifactId>shardingsphere-replica-route</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.shardingsphere</groupId>
             <artifactId>shardingsphere-infra-executor</artifactId>
             <version>${project.version}</version>
         </dependency>
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/callback/DefaultReplicaExecutorCallback.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/callback/DefaultReplicaExecutorCallback.java
new file mode 100644
index 0000000..c1be3fd
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/callback/DefaultReplicaExecutorCallback.java
@@ -0,0 +1,54 @@
+/*
+ * 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.replica.execute.callback;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.infra.exception.ShardingSphereException;
+import org.apache.shardingsphere.infra.executor.sql.raw.RawSQLExecuteUnit;
+import org.apache.shardingsphere.infra.executor.sql.raw.execute.callback.RawExecutorCallback;
+import org.apache.shardingsphere.infra.executor.sql.raw.execute.result.ExecuteResult;
+import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
+
+import java.sql.SQLException;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Default replica executor callback.
+ */
+@Slf4j
+public final class DefaultReplicaExecutorCallback implements RawExecutorCallback<RawSQLExecuteUnit, ExecuteResult> {
+    
+    static {
+        ShardingSphereServiceLoader.register(ReplicaExecutorCallback.class);
+    }
+    
+    private final Collection<ReplicaExecutorCallback> replicaExecutorCallbacks;
+    
+    public DefaultReplicaExecutorCallback() {
+        replicaExecutorCallbacks = ShardingSphereServiceLoader.newServiceInstances(ReplicaExecutorCallback.class);
+        if (null == replicaExecutorCallbacks || replicaExecutorCallbacks.isEmpty()) {
+            throw new ShardingSphereException("not found replica executor callback impl");
+        }
+    }
+    
+    @Override
+    public Collection<ExecuteResult> execute(final Collection<RawSQLExecuteUnit> inputs, final boolean isTrunkThread, final Map<String, Object> dataMap) throws SQLException {
+        return replicaExecutorCallbacks.iterator().next().execute(inputs, isTrunkThread, dataMap);
+    }
+}
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupEngine.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/callback/ReplicaExecutorCallback.java
similarity index 60%
copy from shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupEngine.java
copy to shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/callback/ReplicaExecutorCallback.java
index 37f43d9..e92254c 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupEngine.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/callback/ReplicaExecutorCallback.java
@@ -15,27 +15,28 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.executor.sql.group;
-
-import org.apache.shardingsphere.infra.executor.kernel.InputGroup;
-import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
+package org.apache.shardingsphere.replica.execute.callback;
 
 import java.sql.SQLException;
 import java.util.Collection;
+import java.util.Map;
 
 /**
- * Execute group engine.
- * 
- * @param <T> type of input value
+ * Replica executor callback.
+ *
+ * @param <I> type of input value
+ * @param <O> type of output value
  */
-public interface ExecuteGroupEngine<T> {
+public interface ReplicaExecutorCallback<I, O> {
     
     /**
-     * Generate execution input groups.
+     * Execute.
      *
-     * @param executionUnits execution units
-     * @return execution input groups
-     * @throws SQLException SQL exception
+     * @param inputs input values
+     * @param isTrunkThread is execution in trunk thread
+     * @param dataMap data map
+     * @return execution results
+     * @throws SQLException throw when execute failure
      */
-    Collection<InputGroup<T>> generate(Collection<ExecutionUnit> executionUnits) throws SQLException;
+    Collection<O> execute(Collection<I> inputs, boolean isTrunkThread, Map<String, Object> dataMap) throws SQLException;
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/group/ReplicaExecuteGroupDecorator.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/group/ReplicaExecuteGroupDecorator.java
index 905b07a..79ca868 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/group/ReplicaExecuteGroupDecorator.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/java/org/apache/shardingsphere/replica/execute/group/ReplicaExecuteGroupDecorator.java
@@ -17,38 +17,85 @@
 
 package org.apache.shardingsphere.replica.execute.group;
 
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.infra.exception.ShardingSphereException;
 import org.apache.shardingsphere.infra.executor.kernel.InputGroup;
-import org.apache.shardingsphere.infra.executor.sql.resourced.ResourceManagedExecuteUnit;
-import org.apache.shardingsphere.infra.executor.sql.group.ExecuteGroupDecorator;
+import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
+import org.apache.shardingsphere.infra.executor.sql.context.SQLRuntimeContext;
+import org.apache.shardingsphere.infra.executor.sql.raw.RawSQLExecuteUnit;
+import org.apache.shardingsphere.infra.executor.sql.raw.group.RawExecuteGroupDecorator;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.infra.route.context.RouteStageContext;
 import org.apache.shardingsphere.replica.constant.ReplicaOrder;
+import org.apache.shardingsphere.replica.route.engine.ReplicaGroup;
+import org.apache.shardingsphere.replica.route.engine.ReplicaRouteStageContext;
 import org.apache.shardingsphere.replica.rule.ReplicaRule;
 
 import java.util.Collection;
-import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 
 /**
  * Execute group decorator for replica.
- * 
- * @param <T> type of input value 
  */
-public final class ReplicaExecuteGroupDecorator<T extends ResourceManagedExecuteUnit> implements ExecuteGroupDecorator<T, ReplicaRule> {
+@Slf4j
+public final class ReplicaExecuteGroupDecorator implements RawExecuteGroupDecorator<RawSQLExecuteUnit, ReplicaRule> {
+    
+    /**
+     * TODO FIXED ME when the proxy is capable of handling tableless operation commands, it can be removed.
+     */
+    private final boolean supportWithoutTableCommand = true;
     
     @Override
-    public Collection<InputGroup<T>> decorate(final ReplicaRule rule, final Collection<InputGroup<T>> inputGroups) {
-        Map<String, InputGroup<T>> result = new LinkedHashMap<>(inputGroups.size(), 1);
-        for (InputGroup<T> each : inputGroups) {
-            T sample = each.getInputs().get(0);
-            String dataSourceName = sample.getExecutionUnit().getDataSourceName();
-            Optional<String> logicDataSource = rule.findLogicDataSource(dataSourceName);
-            if (logicDataSource.isPresent() && result.containsKey(dataSourceName)) {
-                result.get(dataSourceName).getInputs().addAll(each.getInputs());
-            } else {
-                result.put(dataSourceName, each);
+    public Collection<InputGroup<RawSQLExecuteUnit>> decorate(final RouteContext routeContext, final ReplicaRule rule, final Collection<InputGroup<RawSQLExecuteUnit>> inputGroups) {
+        if (!inputGroups.isEmpty()) {
+            if (!(inputGroups.iterator().next().getInputs().get(0) instanceof RawSQLExecuteUnit)) {
+                log.debug("inputGroups ExecuteUnit is not RawSQLExecuteUnit, ignore decorate");
+                return inputGroups;
+            }
+        }
+        RouteStageContext routeStageContext = routeContext.getRouteStageContext(getTypeClass());
+        ReplicaRouteStageContext replicaRouteStageContext = (ReplicaRouteStageContext) routeStageContext;
+        Map<String, ReplicaGroup> replicaGroups = replicaRouteStageContext.getReplicaGroups();
+        for (InputGroup<RawSQLExecuteUnit> each : inputGroups) {
+            routeReplicaGroup(each, replicaRouteStageContext.getSchemaName(), replicaGroups, replicaRouteStageContext.isReadOnly());
+        }
+        return inputGroups;
+    }
+    
+    private void routeReplicaGroup(final InputGroup<RawSQLExecuteUnit> inputGroup, final String schemaName, final Map<String, ReplicaGroup> replicaGroups, final boolean readOnly) {
+        for (RawSQLExecuteUnit each : inputGroup.getInputs()) {
+            ExecutionUnit executionUnit = each.getExecutionUnit();
+            SQLRuntimeContext sqlRuntimeContext = executionUnit.getSqlUnit().getSqlRuntimeContext();
+            List<String> actualTables = sqlRuntimeContext.getActualTables();
+            if ((null == actualTables || actualTables.isEmpty()) && !supportWithoutTableCommand) {
+                throw new ShardingSphereException("route fail: actual tables is empty");
             }
+            ReplicaGroup replicaGroup = getReplicaGroup(actualTables, replicaGroups);
+            each.setRawGroup(replicaGroup);
+            sqlRuntimeContext.setSchemaName(schemaName);
+            sqlRuntimeContext.setReadOnly(readOnly);
+        }
+    }
+    
+    private ReplicaGroup getReplicaGroup(final List<String> actualTables, final Map<String, ReplicaGroup> replicaGroups) {
+        ReplicaGroup replicaGroup = null;
+        if (null != actualTables && !actualTables.isEmpty()) {
+            for (String each : actualTables) {
+                replicaGroup = replicaGroups.get(each);
+                if (null != replicaGroup) {
+                    break;
+                }
+            }
+        } else {
+            if (!replicaGroups.isEmpty()) {
+                replicaGroup = replicaGroups.entrySet().iterator().next().getValue();
+            }
+        }
+        if (null == replicaGroup) {
+            throw new ShardingSphereException("route fail: route result is empty");
         }
-        return result.values();
+        return replicaGroup;
     }
     
     @Override
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.executor.sql.raw.execute.callback.RawExecutorCallback b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.executor.sql.raw.execute.callback.RawExecutorCallback
new file mode 100644
index 0000000..32fa8f4
--- /dev/null
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-execute/src/main/resources/META-INF/services/org.apache.shardingsphere.infra.executor.sql.raw.execute.callback.RawExecutorCallback
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+org.apache.shardingsphere.replica.execute.callback.DefaultReplicaExecutorCallback
diff --git a/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaGroup.java
similarity index 64%
copy from shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java
copy to shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaGroup.java
index 17dc764..5309022 100644
--- a/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaGroup.java
@@ -15,24 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.route.context;
+package org.apache.shardingsphere.replica.route.engine;
 
+import lombok.AllArgsConstructor;
 import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
-
-import java.util.List;
+import org.apache.shardingsphere.infra.route.context.RawGroup;
 
 /**
- * Route context.
+ * Replica group.
  */
-@RequiredArgsConstructor
+@AllArgsConstructor
 @Getter
-public final class RouteContext {
+public final class ReplicaGroup implements RawGroup {
+    
+    public static final String BLANK_REPLICA_GROUP_KEY = "Nil";
+    
+    private final String physicsTable;
     
-    private final SQLStatementContext<?> sqlStatementContext;
+    private final String replicaGroupId;
     
-    private final List<Object> parameters;
+    private final String replicaPeers;
     
-    private final RouteResult routeResult;
+    private final String dataSourceName;
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaRouteDecorator.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaRouteDecorator.java
index dd9d81d..1de1da2 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaRouteDecorator.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaRouteDecorator.java
@@ -18,19 +18,19 @@
 package org.apache.shardingsphere.replica.route.engine;
 
 import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties;
-import org.apache.shardingsphere.infra.database.DefaultSchema;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.route.context.RouteMapper;
-import org.apache.shardingsphere.infra.route.context.RouteResult;
 import org.apache.shardingsphere.infra.route.context.RouteUnit;
 import org.apache.shardingsphere.infra.route.decorator.RouteDecorator;
 import org.apache.shardingsphere.replica.constant.ReplicaOrder;
 import org.apache.shardingsphere.replica.rule.ReplicaRule;
+import org.apache.shardingsphere.replica.rule.ReplicaTableRule;
+import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 
 import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -40,29 +40,47 @@ public final class ReplicaRouteDecorator implements RouteDecorator<ReplicaRule>
     
     @Override
     public RouteContext decorate(final RouteContext routeContext, final ShardingSphereMetaData metaData, final ReplicaRule replicaRule, final ConfigurationProperties props) {
+        Map<String, ReplicaGroup> replicaGroups = new HashMap<>();
+        String schemaName = metaData.getSchemaName();
+        SQLStatementContext<?> sqlStatementContext = routeContext.getSqlStatementContext();
         if (routeContext.getRouteResult().getRouteUnits().isEmpty()) {
-            RouteResult routeResult = new RouteResult();
-            for (String each : replicaRule.getSingleReplicaDataSources()) {
-                routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(DefaultSchema.LOGIC_NAME, each), Collections.emptyList()));
-            }
-            return new RouteContext(routeContext.getSqlStatementContext(), Collections.emptyList(), routeResult);
+            ReplicaTableRule replicaRoutingRule = replicaRule.getReplicaTableRules().iterator().next();
+            ReplicaGroup replicaGroup = new ReplicaGroup(replicaRoutingRule.getPhysicsTable(), replicaRoutingRule.getReplicaGroupId(), replicaRoutingRule.getReplicaPeers(),
+                    replicaRoutingRule.getDataSourceName());
+            replicaGroups.put(ReplicaGroup.BLANK_REPLICA_GROUP_KEY, replicaGroup);
+            return new RouteContext(routeContext, routeContext.getRouteResult(), new ReplicaRouteStageContext(schemaName, replicaGroups, sqlStatementContext.isReadOnly()), getTypeClass());
         }
-        Collection<RouteUnit> toBeRemoved = new LinkedList<>();
-        Collection<RouteUnit> toBeAdded = new LinkedList<>();
         for (RouteUnit each : routeContext.getRouteResult().getRouteUnits()) {
-            String dataSourceName = each.getDataSourceMapper().getLogicName();
-            Optional<Collection<String>> replicaDataSources = replicaRule.findReplicaDataSources(dataSourceName);
-            if (!replicaDataSources.isPresent()) {
-                continue;
+            Collection<RouteMapper> routeMappers = each.getTableMappers();
+            if (null == routeMappers || routeMappers.isEmpty()) {
+                ReplicaTableRule replicaRoutingRule = replicaRule.getReplicaTableRules().iterator().next();
+                ReplicaGroup replicaGroup = new ReplicaGroup(replicaRoutingRule.getPhysicsTable(), replicaRoutingRule.getReplicaGroupId(), replicaRoutingRule.getReplicaPeers(),
+                        replicaRoutingRule.getDataSourceName());
+                replicaGroups.put(ReplicaGroup.BLANK_REPLICA_GROUP_KEY, replicaGroup);
+            } else {
+                routeReplicaGroups(routeMappers, replicaRule, replicaGroups);
             }
-            toBeRemoved.add(each);
-            for (String replicaDataSource : replicaDataSources.get()) {
-                toBeAdded.add(new RouteUnit(new RouteMapper(dataSourceName, replicaDataSource), each.getTableMappers()));
+        }
+        return new RouteContext(routeContext, routeContext.getRouteResult(), new ReplicaRouteStageContext(schemaName, replicaGroups, sqlStatementContext.isReadOnly()), getTypeClass());
+    }
+    
+    private void routeReplicaGroups(final Collection<RouteMapper> routeMappers, final ReplicaRule replicaRule, final Map<String, ReplicaGroup> replicaGroups) {
+        for (RouteMapper each : routeMappers) {
+            String actualTableName = each.getActualName();
+            Optional<ReplicaTableRule> replicaRoutingRuleOptional = replicaRule.findRoutingByTable(actualTableName);
+            ReplicaGroup replicaGroup;
+            if (replicaRoutingRuleOptional.isPresent()) {
+                ReplicaTableRule replicaRoutingRule = replicaRoutingRuleOptional.get();
+                replicaGroup = new ReplicaGroup(replicaRoutingRule.getPhysicsTable(), replicaRoutingRule.getReplicaGroupId(), replicaRoutingRule.getReplicaPeers(),
+                        replicaRoutingRule.getDataSourceName());
+                replicaGroups.put(actualTableName, replicaGroup);
+            } else {
+                ReplicaTableRule replicaRoutingRule = replicaRule.getReplicaTableRules().iterator().next();
+                replicaGroup = new ReplicaGroup(replicaRoutingRule.getPhysicsTable(), replicaRoutingRule.getReplicaGroupId(), replicaRoutingRule.getReplicaPeers(),
+                        replicaRoutingRule.getDataSourceName());
             }
+            replicaGroups.put(actualTableName, replicaGroup);
         }
-        routeContext.getRouteResult().getRouteUnits().removeAll(toBeRemoved);
-        routeContext.getRouteResult().getRouteUnits().addAll(toBeAdded);
-        return routeContext;
     }
     
     @Override
diff --git a/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaRouteStageContext.java
similarity index 70%
copy from shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java
copy to shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaRouteStageContext.java
index 17dc764..1715c66 100644
--- a/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java
+++ b/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-route/src/main/java/org/apache/shardingsphere/replica/route/engine/ReplicaRouteStageContext.java
@@ -15,24 +15,24 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.infra.route.context;
+package org.apache.shardingsphere.replica.route.engine;
 
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.route.context.RouteStageContext;
 
-import java.util.List;
+import java.util.Map;
 
 /**
- * Route context.
+ * Replica route stage context.
  */
 @RequiredArgsConstructor
 @Getter
-public final class RouteContext {
+public final class ReplicaRouteStageContext implements RouteStageContext {
     
-    private final SQLStatementContext<?> sqlStatementContext;
+    private final String schemaName;
     
-    private final List<Object> parameters;
+    private final Map<String, ReplicaGroup> replicaGroups;
     
-    private final RouteResult routeResult;
+    private final boolean readOnly;
 }
diff --git a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteDecorator.java b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteDecorator.java
index 2bf7119..1e29f56 100644
--- a/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteDecorator.java
+++ b/shardingsphere-features/shardingsphere-shadow/shardingsphere-shadow-route/src/main/java/org/apache/shardingsphere/shadow/route/engine/ShadowRouteDecorator.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.shadow.route.engine;
 
+import org.apache.shardingsphere.infra.route.context.DefaultRouteStageContext;
 import org.apache.shardingsphere.shadow.constant.ShadowOrder;
 import org.apache.shardingsphere.shadow.route.engine.judge.ShadowDataSourceJudgeEngine;
 import org.apache.shardingsphere.shadow.rule.ShadowRule;
@@ -52,20 +53,19 @@ public final class ShadowRouteDecorator implements RouteDecorator<ShadowRule> {
         SQLStatementContext<?> sqlStatementContext = routeContext.getSqlStatementContext();
         SQLStatement sqlStatement = sqlStatementContext.getSqlStatement();
         RouteResult routeResult = new RouteResult();
-        List<Object> parameters = routeContext.getParameters();
         if (!(sqlStatement instanceof DMLStatement)) {
             shadowRule.getShadowMappings().forEach((key, value) -> {
                 routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(key, key), Collections.emptyList()));
                 routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(value, value), Collections.emptyList()));
             });
-            return new RouteContext(sqlStatementContext, parameters, routeResult);
+            return new RouteContext(routeContext, routeResult, new DefaultRouteStageContext(), getTypeClass());
         }
         if (isShadow(routeContext, shadowRule)) {
             shadowRule.getShadowMappings().values().forEach(each -> routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(each, each), Collections.emptyList())));
         } else {
             shadowRule.getShadowMappings().keySet().forEach(each -> routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper(each, each), Collections.emptyList())));
         }
-        return new RouteContext(sqlStatementContext, parameters, routeResult);
+        return new RouteContext(routeContext, routeResult, new DefaultRouteStageContext(), getTypeClass());
     }
     
     private RouteContext getRouteContextWithRouteResult(final RouteContext routeContext, final ShadowRule shadowRule) {
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/java/org/apache/shardingsphere/sharding/rewrite/parameterized/MixSQLRewriterParameterizedTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/java/org/apache/shardingsphere/sharding/rewrite/parameterized/MixSQLRewriterParameterizedTest.java
index 1cf7a04..25e50c4 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/java/org/apache/shardingsphere/sharding/rewrite/parameterized/MixSQLRewriterParameterizedTest.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/java/org/apache/shardingsphere/sharding/rewrite/parameterized/MixSQLRewriterParameterizedTest.java
@@ -82,7 +82,7 @@ public final class MixSQLRewriterParameterizedTest extends AbstractSQLRewriterPa
         ConfigurationProperties props = new ConfigurationProperties(ruleConfigurations.getProps());
         RouteContext routeContext = new DataNodeRouter(metaData, props, rules).route(
                 standardSqlParserEngine.parse(getTestParameters().getInputSQL(), false), getTestParameters().getInputSQL(), getTestParameters().getInputParameters());
-        SQLRewriteResult sqlRewriteResult = new SQLRewriteEntry(metaData.getRuleSchemaMetaData().getConfiguredSchemaMetaData(), 
+        SQLRewriteResult sqlRewriteResult = new SQLRewriteEntry(metaData.getRuleSchemaMetaData().getConfiguredSchemaMetaData(),
                 props, rules).rewrite(getTestParameters().getInputSQL(), getTestParameters().getInputParameters(), routeContext);
         return sqlRewriteResult instanceof GenericSQLRewriteResult
                 ? Collections.singletonList(((GenericSQLRewriteResult) sqlRewriteResult).getSqlRewriteUnit()) : (((RouteSQLRewriteResult) sqlRewriteResult).getSqlRewriteUnits()).values();
@@ -114,7 +114,7 @@ public final class MixSQLRewriterParameterizedTest extends AbstractSQLRewriterPa
         RuleSchemaMetaData ruleSchemaMetaData = mock(RuleSchemaMetaData.class);
         when(ruleSchemaMetaData.getConfiguredSchemaMetaData()).thenReturn(schemaMetaData);
         when(ruleSchemaMetaData.getSchemaMetaData()).thenReturn(schemaMetaData);
-        return new ShardingSphereMetaData(mock(DataSourceMetaDatas.class), ruleSchemaMetaData);
+        return new ShardingSphereMetaData(mock(DataSourceMetaDatas.class), ruleSchemaMetaData, "sharding_db");
     }
     
     private Map<String, ColumnMetaData> createColumnMetaDataMap() {
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/java/org/apache/shardingsphere/sharding/rewrite/parameterized/ShardingSQLRewriterParameterizedTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/java/org/apache/shardingsphere/sharding/rewrite/parameterized/ShardingSQLRewriterParameterizedTest.java
index 1804deb..7991254 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/java/org/apache/shardingsphere/sharding/rewrite/parameterized/ShardingSQLRewriterParameterizedTest.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-rewrite/src/test/java/org/apache/shardingsphere/sharding/rewrite/parameterized/ShardingSQLRewriterParameterizedTest.java
@@ -109,7 +109,7 @@ public final class ShardingSQLRewriterParameterizedTest extends AbstractSQLRewri
         RuleSchemaMetaData ruleSchemaMetaData = mock(RuleSchemaMetaData.class);
         when(ruleSchemaMetaData.getConfiguredSchemaMetaData()).thenReturn(schemaMetaData);
         when(ruleSchemaMetaData.getSchemaMetaData()).thenReturn(schemaMetaData);
-        return new ShardingSphereMetaData(mock(DataSourceMetaDatas.class), ruleSchemaMetaData);
+        return new ShardingSphereMetaData(mock(DataSourceMetaDatas.class), ruleSchemaMetaData, "sharding_db");
     }
     
     private Map<String, ColumnMetaData> createColumnMetaDataMap() {
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/ShardingRouteDecorator.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/ShardingRouteDecorator.java
index 041b0e1..388feee 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/ShardingRouteDecorator.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/main/java/org/apache/shardingsphere/sharding/route/engine/ShardingRouteDecorator.java
@@ -21,6 +21,7 @@ import com.google.common.base.Preconditions;
 import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties;
 import org.apache.shardingsphere.infra.hint.HintManager;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import org.apache.shardingsphere.infra.route.context.DefaultRouteStageContext;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.route.context.RouteResult;
 import org.apache.shardingsphere.infra.route.decorator.RouteDecorator;
@@ -73,7 +74,7 @@ public final class ShardingRouteDecorator implements RouteDecorator<ShardingRule
         ShardingRouteEngine shardingRouteEngine = ShardingRouteEngineFactory.newInstance(shardingRule, metaData, sqlStatementContext, shardingConditions, props);
         RouteResult routeResult = shardingRouteEngine.route(shardingRule);
         shardingStatementValidator.ifPresent(validator -> validator.postValidate(sqlStatement, routeResult));
-        return new RouteContext(sqlStatementContext, parameters, routeResult);
+        return new RouteContext(routeContext, routeResult, new DefaultRouteStageContext(), getTypeClass());
     }
 
     private ShardingConditions getShardingConditions(final List<Object> parameters, final SQLStatementContext sqlStatementContext,
diff --git a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/AbstractSQLRouteTest.java b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/AbstractSQLRouteTest.java
index 0630937..299968f 100644
--- a/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/AbstractSQLRouteTest.java
+++ b/shardingsphere-features/shardingsphere-sharding/shardingsphere-sharding-route/src/test/java/org/apache/shardingsphere/sharding/route/engine/type/standard/AbstractSQLRouteTest.java
@@ -49,7 +49,7 @@ public abstract class AbstractSQLRouteTest extends AbstractRoutingEngineTest {
     
     protected final RouteContext assertRoute(final String sql, final List<Object> parameters) {
         ShardingRule shardingRule = createAllShardingRule();
-        ShardingSphereMetaData metaData = new ShardingSphereMetaData(buildDataSourceMetas(), buildRuleSchemaMetaData());
+        ShardingSphereMetaData metaData = new ShardingSphereMetaData(buildDataSourceMetas(), buildRuleSchemaMetaData(), "sharding_db");
         ConfigurationProperties props = new ConfigurationProperties(new Properties());
         StandardSQLParserEngine standardSqlParserEngine = SQLParserEngineFactory.getSQLParserEngine("MySQL");
         RouteContext routeContext = new DataNodeRouter(metaData, props, Collections.singletonList(shardingRule)).route(standardSqlParserEngine.parse(sql, false), sql, parameters);
diff --git a/shardingsphere-governance/shardingsphere-governance-core/shardingsphere-governance-core-context/src/main/java/org/apache/shardingsphere/governance/context/schema/GovernanceSchemaContexts.java b/shardingsphere-governance/shardingsphere-governance-core/shardingsphere-governance-core-context/src/main/java/org/apache/shardingsphere/governance/context/schema/GovernanceSchemaContexts.java
index b400f16..fc348ee 100644
--- a/shardingsphere-governance/shardingsphere-governance-core/shardingsphere-governance-core-context/src/main/java/org/apache/shardingsphere/governance/context/schema/GovernanceSchemaContexts.java
+++ b/shardingsphere-governance/shardingsphere-governance-core/shardingsphere-governance-core-context/src/main/java/org/apache/shardingsphere/governance/context/schema/GovernanceSchemaContexts.java
@@ -158,7 +158,7 @@ public final class GovernanceSchemaContexts implements SchemaContexts {
         Map<String, SchemaContext> schemas = new HashMap<>(schemaContexts.getSchemaContexts());
         schemas.put(event.getSchemaName(), createAddedSchemaContext(event));
         schemaContexts = new StandardSchemaContexts(schemas, schemaContexts.getAuthentication(), schemaContexts.getProps(), schemaContexts.getDatabaseType());
-        governanceFacade.getMetaDataCenter().persistMetaDataCenterNode(event.getSchemaName(), 
+        governanceFacade.getMetaDataCenter().persistMetaDataCenterNode(event.getSchemaName(),
                 schemaContexts.getSchemaContexts().get(event.getSchemaName()).getSchema().getMetaData().getRuleSchemaMetaData());
         ShardingSphereEventBus.getInstance().post(
                 new DataSourceChangeCompletedEvent(event.getSchemaName(), schemaContexts.getDatabaseType(), schemas.get(event.getSchemaName()).getSchema().getDataSources()));
@@ -209,8 +209,8 @@ public final class GovernanceSchemaContexts implements SchemaContexts {
             String schemaName = entry.getKey();
             SchemaContext oldSchemaContext = entry.getValue();
             SchemaContext newSchemaContext = event.getSchemaNames().contains(schemaName) 
-                    ? new SchemaContext(oldSchemaContext.getName(), getChangedShardingSphereSchema(oldSchemaContext.getSchema(), event.getRuleSchemaMetaData()), oldSchemaContext.getRuntimeContext())
-                    : oldSchemaContext;
+                    ? new SchemaContext(oldSchemaContext.getName(), getChangedShardingSphereSchema(oldSchemaContext.getSchema(), event.getRuleSchemaMetaData(), schemaName),
+                    oldSchemaContext.getRuntimeContext()) : oldSchemaContext;
             newSchemaContexts.put(schemaName, newSchemaContext);
         }
         schemaContexts = new StandardSchemaContexts(newSchemaContexts, schemaContexts.getAuthentication(), schemaContexts.getProps(), schemaContexts.getDatabaseType());
@@ -295,8 +295,8 @@ public final class GovernanceSchemaContexts implements SchemaContexts {
         return result;
     }
     
-    private ShardingSphereSchema getChangedShardingSphereSchema(final ShardingSphereSchema oldShardingSphereSchema, final RuleSchemaMetaData newRuleSchemaMetaData) {
-        ShardingSphereMetaData metaData = new ShardingSphereMetaData(oldShardingSphereSchema.getMetaData().getDataSourceMetaDatas(), newRuleSchemaMetaData);
+    private ShardingSphereSchema getChangedShardingSphereSchema(final ShardingSphereSchema oldShardingSphereSchema, final RuleSchemaMetaData newRuleSchemaMetaData, final String schemaName) {
+        ShardingSphereMetaData metaData = new ShardingSphereMetaData(oldShardingSphereSchema.getMetaData().getDataSourceMetaDatas(), newRuleSchemaMetaData, schemaName);
         return new ShardingSphereSchema(oldShardingSphereSchema.getConfigurations(), oldShardingSphereSchema.getRules(), oldShardingSphereSchema.getDataSources(), metaData);
     }
     
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/ShardingSphereMetaData.java b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/ShardingSphereMetaData.java
index ca320c3..12538e1 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/ShardingSphereMetaData.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/main/java/org/apache/shardingsphere/infra/metadata/ShardingSphereMetaData.java
@@ -32,4 +32,6 @@ public final class ShardingSphereMetaData {
     private final DataSourceMetaDatas dataSourceMetaDatas;
     
     private final RuleSchemaMetaData ruleSchemaMetaData;
+    
+    private final String schemaName;
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/AbstractMetaDataRefreshStrategyTest.java b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/AbstractMetaDataRefreshStrategyTest.java
index 6ac1d93..930b191 100644
--- a/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/AbstractMetaDataRefreshStrategyTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-common/src/test/java/org/apache/shardingsphere/infra/metadata/refresh/AbstractMetaDataRefreshStrategyTest.java
@@ -42,7 +42,8 @@ public abstract class AbstractMetaDataRefreshStrategyTest {
         return new ShardingSphereMetaData(null, new RuleSchemaMetaData(new SchemaMetaData(ImmutableMap
             .of("t_order", new TableMetaData(Collections.singletonList(new ColumnMetaData("order_id", 1, "String", false, false, false)), Collections.singletonList(new IndexMetaData("index"))))),
             ImmutableMap.of("t_order_item", new SchemaMetaData(ImmutableMap.of("t_order_item",
-                new TableMetaData(Collections.singletonList(new ColumnMetaData("order_item_id", 1, "String", true, false, false)), Collections.singletonList(new IndexMetaData("index"))))))));
+                new TableMetaData(Collections.singletonList(new ColumnMetaData("order_item_id", 1, "String", true, false, false)), Collections.singletonList(new IndexMetaData("index"))))))),
+                "sharding_db");
     }
 }
 
diff --git a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/SchemaContextsBuilder.java b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/SchemaContextsBuilder.java
index b954ec3..77d9678 100644
--- a/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/SchemaContextsBuilder.java
+++ b/shardingsphere-infra/shardingsphere-infra-context/src/main/java/org/apache/shardingsphere/infra/context/SchemaContextsBuilder.java
@@ -123,7 +123,7 @@ public final class SchemaContextsBuilder {
         long start = System.currentTimeMillis();
         DataSourceMetaDatas dataSourceMetas = new DataSourceMetaDatas(databaseType, getDatabaseAccessConfigurationMap(dataSourceMap));
         RuleSchemaMetaData ruleSchemaMetaData = new RuleSchemaMetaDataLoader(rules).load(databaseType, dataSourceMap, props);
-        ShardingSphereMetaData result = new ShardingSphereMetaData(dataSourceMetas, ruleSchemaMetaData);
+        ShardingSphereMetaData result = new ShardingSphereMetaData(dataSourceMetas, ruleSchemaMetaData, schemaName);
         log.info("Load meta data for schema {} finished, cost {} milliseconds.", schemaName, System.currentTimeMillis() - start);
         return result;
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContext.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContext.java
index 5d18534..e06a8c4 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContext.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContext.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.infra.executor.sql.context;
 
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 
 import java.util.Collection;
@@ -35,7 +36,9 @@ public final class ExecutionContext {
     
     private final Collection<ExecutionUnit> executionUnits;
     
-    public ExecutionContext(final SQLStatementContext<?> sqlStatementContext, final ExecutionUnit executionUnit) {
-        this(sqlStatementContext, Collections.singletonList(executionUnit));
+    private final RouteContext routeContext;
+
+    public ExecutionContext(final SQLStatementContext<?> sqlStatementContext, final ExecutionUnit executionUnit, final RouteContext routeContext) {
+        this(sqlStatementContext, Collections.singletonList(executionUnit), routeContext);
     }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContextBuilder.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContextBuilder.java
index b6eccb0..0e1d715 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContextBuilder.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContextBuilder.java
@@ -24,12 +24,18 @@ import org.apache.shardingsphere.infra.rewrite.engine.result.GenericSQLRewriteRe
 import org.apache.shardingsphere.infra.rewrite.engine.result.RouteSQLRewriteResult;
 import org.apache.shardingsphere.infra.rewrite.engine.result.SQLRewriteResult;
 import org.apache.shardingsphere.infra.rewrite.engine.result.SQLRewriteUnit;
+import org.apache.shardingsphere.infra.route.context.RouteMapper;
 import org.apache.shardingsphere.infra.route.context.RouteUnit;
+import org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext;
+import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map.Entry;
+import java.util.stream.Collectors;
 
 /**
  * Execution context builder.
@@ -42,21 +48,87 @@ public final class ExecutionContextBuilder {
      * 
      * @param metaData meta data
      * @param sqlRewriteResult SQL rewrite result
+     * @param sqlStatementContext SQL statement context
      * @return execution contexts
      */
-    public static Collection<ExecutionUnit> build(final ShardingSphereMetaData metaData, final SQLRewriteResult sqlRewriteResult) {
-        return sqlRewriteResult instanceof GenericSQLRewriteResult ? build(metaData, (GenericSQLRewriteResult) sqlRewriteResult) : build((RouteSQLRewriteResult) sqlRewriteResult);
+    public static Collection<ExecutionUnit> build(final ShardingSphereMetaData metaData, final SQLRewriteResult sqlRewriteResult, final SQLStatementContext<?> sqlStatementContext) {
+        return sqlRewriteResult instanceof GenericSQLRewriteResult ? build(metaData, (GenericSQLRewriteResult) sqlRewriteResult, sqlStatementContext)
+                : build(metaData, (RouteSQLRewriteResult) sqlRewriteResult);
     }
     
-    private static Collection<ExecutionUnit> build(final ShardingSphereMetaData metaData, final GenericSQLRewriteResult sqlRewriteResult) {
+    private static Collection<ExecutionUnit> build(final ShardingSphereMetaData metaData, final GenericSQLRewriteResult sqlRewriteResult, final SQLStatementContext<?> sqlStatementContext) {
         String dataSourceName = metaData.getDataSourceMetaDatas().getAllInstanceDataSourceNames().iterator().next();
-        return Collections.singletonList(new ExecutionUnit(dataSourceName, new SQLUnit(sqlRewriteResult.getSqlRewriteUnit().getSql(), sqlRewriteResult.getSqlRewriteUnit().getParameters())));
+        return Collections.singletonList(new ExecutionUnit(dataSourceName,
+                new SQLUnit(sqlRewriteResult.getSqlRewriteUnit().getSql(), sqlRewriteResult.getSqlRewriteUnit().getParameters(), getSQLRuntimeContext(metaData, sqlStatementContext))));
     }
     
-    private static Collection<ExecutionUnit> build(final RouteSQLRewriteResult sqlRewriteResult) {
+    private static Collection<ExecutionUnit> build(final ShardingSphereMetaData metaData, final RouteSQLRewriteResult sqlRewriteResult) {
         Collection<ExecutionUnit> result = new LinkedHashSet<>();
         for (Entry<RouteUnit, SQLRewriteUnit> entry : sqlRewriteResult.getSqlRewriteUnits().entrySet()) {
-            result.add(new ExecutionUnit(entry.getKey().getDataSourceMapper().getActualName(), new SQLUnit(entry.getValue().getSql(), entry.getValue().getParameters())));
+            Collection<RouteMapper> tableMappers = entry.getKey().getTableMappers();
+            result.add(new ExecutionUnit(entry.getKey().getDataSourceMapper().getActualName(),
+                    new SQLUnit(entry.getValue().getSql(), entry.getValue().getParameters(), getSQLRuntimeContext(metaData, tableMappers))));
+        }
+        return result;
+    }
+    
+    private static SQLRuntimeContext getSQLRuntimeContext(final ShardingSphereMetaData metaData, final SQLStatementContext<?> sqlStatementContext) {
+        return new SQLRuntimeContext(getLogicTableNames(sqlStatementContext), getActualTableNames(sqlStatementContext), getPrimaryKeyColumns(metaData, sqlStatementContext));
+    }
+    
+    private static SQLRuntimeContext getSQLRuntimeContext(final ShardingSphereMetaData metaData, final Collection<RouteMapper> tableMappers) {
+        return new SQLRuntimeContext(getLogicTableNames(tableMappers), getActualTableNames(tableMappers), getPrimaryKeyColumns(metaData, tableMappers));
+    }
+    
+    private static List<String> getLogicTableNames(final SQLStatementContext<?> sqlStatementContext) {
+        return getGenericTableNames(sqlStatementContext);
+    }
+    
+    private static List<String> getLogicTableNames(final Collection<RouteMapper> tableMappers) {
+        if (null == tableMappers) {
+            return Collections.emptyList();
+        }
+        return tableMappers.stream().map(RouteMapper::getLogicName).collect(Collectors.toList());
+    }
+    
+    private static List<String> getActualTableNames(final SQLStatementContext<?> sqlStatementContext) {
+        return getGenericTableNames(sqlStatementContext);
+    }
+    
+    private static List<String> getActualTableNames(final Collection<RouteMapper> tableMappers) {
+        if (null == tableMappers) {
+            return Collections.emptyList();
+        }
+        return tableMappers.stream().map(RouteMapper::getActualName).collect(Collectors.toList());
+    }
+    
+    private static List<String> getGenericTableNames(final SQLStatementContext<?> sqlStatementContext) {
+        TablesContext tablesContext = null;
+        if (null != sqlStatementContext) {
+            tablesContext = sqlStatementContext.getTablesContext();
+        }
+        if (null != tablesContext) {
+            return tablesContext.getTableNames().stream().collect(Collectors.toList());
+        }
+        return Collections.emptyList();
+    }
+    
+    private static List<PrimaryKeyMetaData> getPrimaryKeyColumns(final ShardingSphereMetaData metaData, final SQLStatementContext<?> sqlStatementContext) {
+        return getPrimaryKeyColumns(metaData, getActualTableNames(sqlStatementContext));
+    }
+    
+    private static List<PrimaryKeyMetaData> getPrimaryKeyColumns(final ShardingSphereMetaData metaData, final List<String> actualTableNames) {
+        List<PrimaryKeyMetaData> result = new LinkedList<>();
+        for (String each: actualTableNames) {
+            result.add(new PrimaryKeyMetaData(each, metaData.getRuleSchemaMetaData().getSchemaMetaData().get(each).getPrimaryKeyColumns()));
+        }
+        return result;
+    }
+    
+    private static List<PrimaryKeyMetaData> getPrimaryKeyColumns(final ShardingSphereMetaData metaData, final Collection<RouteMapper> tableMappers) {
+        List<PrimaryKeyMetaData> result = new LinkedList<>();
+        for (RouteMapper each: tableMappers) {
+            result.add(new PrimaryKeyMetaData(each.getLogicName(), metaData.getRuleSchemaMetaData().getSchemaMetaData().get(each.getLogicName()).getPrimaryKeyColumns()));
         }
         return result;
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/PrimaryKeyMetaData.java
similarity index 85%
copy from shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java
copy to shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/PrimaryKeyMetaData.java
index f1f785e..bd4b9eb 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/PrimaryKeyMetaData.java
@@ -17,7 +17,6 @@
 
 package org.apache.shardingsphere.infra.executor.sql.context;
 
-import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
@@ -25,15 +24,14 @@ import lombok.ToString;
 import java.util.List;
 
 /**
- * SQL unit.
+ * Primary key meta data.
  */
 @RequiredArgsConstructor
 @Getter
-@EqualsAndHashCode(of = "sql")
 @ToString
-public final class SQLUnit {
+public final class PrimaryKeyMetaData {
     
-    private final String sql;
+    private final String logicTable;
     
-    private final List<Object> parameters;
+    private final List<String> primaryKeyColumns;
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLRuntimeContext.java
similarity index 75%
copy from shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java
copy to shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLRuntimeContext.java
index f1f785e..3952748 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLRuntimeContext.java
@@ -17,23 +17,30 @@
 
 package org.apache.shardingsphere.infra.executor.sql.context;
 
-import lombok.EqualsAndHashCode;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import lombok.ToString;
 
 import java.util.List;
 
 /**
- * SQL unit.
+ * SQL runtime context.
  */
 @RequiredArgsConstructor
 @Getter
-@EqualsAndHashCode(of = "sql")
 @ToString
-public final class SQLUnit {
+public final class SQLRuntimeContext {
     
-    private final String sql;
+    @Setter
+    private String schemaName;
     
-    private final List<Object> parameters;
+    private final List<String> logicTables;
+    
+    private final List<String> actualTables;
+    
+    private final List<PrimaryKeyMetaData> primaryKeyMetaDatas;
+    
+    @Setter
+    private boolean readOnly;
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java
index f1f785e..3bddaf8 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/context/SQLUnit.java
@@ -22,6 +22,7 @@ import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -36,4 +37,10 @@ public final class SQLUnit {
     private final String sql;
     
     private final List<Object> parameters;
+    
+    private final SQLRuntimeContext sqlRuntimeContext;
+    
+    public SQLUnit(final String sql, final List<Object> parameters) {
+        this(sql, parameters, new SQLRuntimeContext(Collections.emptyList(), Collections.emptyList(), Collections.emptyList()));
+    }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/AbstractExecuteGroupEngine.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/AbstractExecuteGroupEngine.java
index e3598ca..7b5e45f 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/AbstractExecuteGroupEngine.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/AbstractExecuteGroupEngine.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.infra.executor.sql.group;
 import org.apache.shardingsphere.infra.executor.kernel.InputGroup;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
 import org.apache.shardingsphere.infra.executor.sql.context.SQLUnit;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
 import org.apache.shardingsphere.infra.spi.order.OrderedSPIRegistry;
@@ -51,12 +52,12 @@ public abstract class AbstractExecuteGroupEngine<T> implements ExecuteGroupEngin
     }
     
     @Override
-    public final Collection<InputGroup<T>> generate(final Collection<ExecutionUnit> executionUnits) throws SQLException {
+    public final Collection<InputGroup<T>> generate(final RouteContext routeContext, final Collection<ExecutionUnit> executionUnits) throws SQLException {
         Collection<InputGroup<T>> result = new LinkedList<>();
         for (Entry<String, List<SQLUnit>> entry : aggregateSQLUnitGroups(executionUnits).entrySet()) {
             result.addAll(generateSQLExecuteGroups(entry.getKey(), entry.getValue()));
         }
-        return decorate(result);
+        return decorate(routeContext, result);
     }
     
     private Map<String, List<SQLUnit>> aggregateSQLUnitGroups(final Collection<ExecutionUnit> executionUnits) {
@@ -73,10 +74,10 @@ public abstract class AbstractExecuteGroupEngine<T> implements ExecuteGroupEngin
     protected abstract List<InputGroup<T>> generateSQLExecuteGroups(String dataSourceName, List<SQLUnit> sqlUnits) throws SQLException;
     
     @SuppressWarnings({"unchecked", "rawtypes"})
-    private Collection<InputGroup<T>> decorate(final Collection<InputGroup<T>> inputGroups) {
+    private Collection<InputGroup<T>> decorate(final RouteContext routeContext, final Collection<InputGroup<T>> inputGroups) {
         Collection<InputGroup<T>> result = inputGroups;
         for (Entry<ShardingSphereRule, ExecuteGroupDecorator> each : decorators.entrySet()) {
-            result = each.getValue().decorate(each.getKey(), result);
+            result = each.getValue().decorate(routeContext, each.getKey(), result);
         }
         return result;
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupDecorator.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupDecorator.java
index 4568465..5454e6c 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupDecorator.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupDecorator.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.infra.executor.sql.group;
 
+import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.infra.spi.order.OrderedSPI;
 import org.apache.shardingsphere.infra.executor.kernel.InputGroup;
@@ -34,9 +35,10 @@ public interface ExecuteGroupDecorator<T, R extends ShardingSphereRule> extends
     /**
      * Decorate input groups.
      * 
+     * @param routeContext route context
      * @param rule ShardingSphere rule
      * @param inputGroups input groups to be decorated
      * @return decorated input groups.
      */
-    Collection<InputGroup<T>> decorate(R rule, Collection<InputGroup<T>> inputGroups);
+    Collection<InputGroup<T>> decorate(RouteContext routeContext, R rule, Collection<InputGroup<T>> inputGroups);
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupEngine.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupEngine.java
index 37f43d9..7641194 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupEngine.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/group/ExecuteGroupEngine.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.infra.executor.sql.group;
 
 import org.apache.shardingsphere.infra.executor.kernel.InputGroup;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
 
 import java.sql.SQLException;
 import java.util.Collection;
@@ -33,9 +34,10 @@ public interface ExecuteGroupEngine<T> {
     /**
      * Generate execution input groups.
      *
+     * @param routeContext route context
      * @param executionUnits execution units
      * @return execution input groups
      * @throws SQLException SQL exception
      */
-    Collection<InputGroup<T>> generate(Collection<ExecutionUnit> executionUnits) throws SQLException;
+    Collection<InputGroup<T>> generate(RouteContext routeContext, Collection<ExecutionUnit> executionUnits) throws SQLException;
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/RawSQLExecuteUnit.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/RawSQLExecuteUnit.java
index 9edfef1..5b04c02 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/RawSQLExecuteUnit.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/RawSQLExecuteUnit.java
@@ -19,8 +19,10 @@ package org.apache.shardingsphere.infra.executor.sql.raw;
 
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import lombok.Setter;
 import org.apache.shardingsphere.infra.executor.sql.ConnectionMode;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
+import org.apache.shardingsphere.infra.route.context.RawGroup;
 
 /**
  * Raw SQL execute unit.
@@ -32,4 +34,7 @@ public final class RawSQLExecuteUnit {
     private final ExecutionUnit executionUnit;
     
     private final ConnectionMode connectionMode;
+
+    @Setter
+    private RawGroup rawGroup;
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawSQLExecutorCallback.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawExecutorCallback.java
similarity index 61%
copy from shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawSQLExecutorCallback.java
copy to shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawExecutorCallback.java
index 8323aae..2ff7043 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawSQLExecutorCallback.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawExecutorCallback.java
@@ -17,21 +17,26 @@
 
 package org.apache.shardingsphere.infra.executor.sql.raw.execute.callback;
 
-import org.apache.shardingsphere.infra.executor.kernel.ExecutorCallback;
-import org.apache.shardingsphere.infra.executor.sql.raw.RawSQLExecuteUnit;
-import org.apache.shardingsphere.infra.executor.sql.raw.execute.result.ExecuteResult;
-
+import java.sql.SQLException;
 import java.util.Collection;
 import java.util.Map;
 
 /**
- * Raw SQL executor callback.
+ * Raw executor callback.
+ *
+ * @param <I> type of input value
+ * @param <O> type of output value
  */
-public final class RawSQLExecutorCallback implements ExecutorCallback<RawSQLExecuteUnit, ExecuteResult> {
+public interface RawExecutorCallback<I, O> {
     
-    @Override
-    public Collection<ExecuteResult> execute(final Collection<RawSQLExecuteUnit> inputs, final boolean isTrunkThread, final Map<String, Object> dataMap) {
-        // TODO
-        return null;
-    }
+    /**
+     * Execute.
+     *
+     * @param inputs input values
+     * @param isTrunkThread is execution in trunk thread
+     * @param dataMap data map
+     * @return execution results
+     * @throws SQLException throw when execute failure
+     */
+    Collection<O> execute(Collection<I> inputs, boolean isTrunkThread, Map<String, Object> dataMap) throws SQLException;
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawSQLExecutorCallback.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawSQLExecutorCallback.java
index 8323aae..d40d95e 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawSQLExecutorCallback.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/execute/callback/RawSQLExecutorCallback.java
@@ -17,21 +17,38 @@
 
 package org.apache.shardingsphere.infra.executor.sql.raw.execute.callback;
 
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shardingsphere.infra.exception.ShardingSphereException;
 import org.apache.shardingsphere.infra.executor.kernel.ExecutorCallback;
 import org.apache.shardingsphere.infra.executor.sql.raw.RawSQLExecuteUnit;
 import org.apache.shardingsphere.infra.executor.sql.raw.execute.result.ExecuteResult;
+import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
 
+import java.sql.SQLException;
 import java.util.Collection;
 import java.util.Map;
 
 /**
  * Raw SQL executor callback.
  */
+@Slf4j
 public final class RawSQLExecutorCallback implements ExecutorCallback<RawSQLExecuteUnit, ExecuteResult> {
-    
+
+    static {
+        ShardingSphereServiceLoader.register(RawExecutorCallback.class);
+    }
+
+    private final Collection<RawExecutorCallback> rawExecutorCallbacks;
+
+    public RawSQLExecutorCallback() {
+        rawExecutorCallbacks = ShardingSphereServiceLoader.newServiceInstances(RawExecutorCallback.class);
+        if (null == rawExecutorCallbacks || rawExecutorCallbacks.isEmpty()) {
+            throw new ShardingSphereException("not found raw executor callback impl");
+        }
+    }
+
     @Override
-    public Collection<ExecuteResult> execute(final Collection<RawSQLExecuteUnit> inputs, final boolean isTrunkThread, final Map<String, Object> dataMap) {
-        // TODO
-        return null;
+    public Collection<ExecuteResult> execute(final Collection<RawSQLExecuteUnit> inputs, final boolean isTrunkThread, final Map<String, Object> dataMap) throws SQLException {
+        return rawExecutorCallbacks.iterator().next().execute(inputs, isTrunkThread, dataMap);
     }
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaRuleConfiguration.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/group/RawExecuteGroupDecorator.java
similarity index 65%
copy from shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaRuleConfiguration.java
copy to shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/group/RawExecuteGroupDecorator.java
index 6149a0a..4bcdd7a 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-api/src/main/java/org/apache/shardingsphere/replica/api/config/ReplicaRuleConfiguration.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/raw/group/RawExecuteGroupDecorator.java
@@ -15,20 +15,16 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.replica.api.config;
+package org.apache.shardingsphere.infra.executor.sql.raw.group;
 
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.infra.config.RuleConfiguration;
-
-import java.util.Collection;
+import org.apache.shardingsphere.infra.executor.sql.group.ExecuteGroupDecorator;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 
 /**
- * Replica rule configuration.
+ * Raw execute group decorator.
+ *
+ * @param <T> type of input value
+ * @param <R> type of ShardingSphere rule
  */
-@RequiredArgsConstructor
-@Getter
-public final class ReplicaRuleConfiguration implements RuleConfiguration {
-    
-    private final Collection<ReplicaDataSourceConfiguration> dataSources;
+public interface RawExecuteGroupDecorator<T, R extends ShardingSphereRule> extends ExecuteGroupDecorator<T, R> {
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/group/ResourceManagedExecuteGroupEngine.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/group/ResourceManagedExecuteGroupEngine.java
index 6a8c92a..164b7b9 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/group/ResourceManagedExecuteGroupEngine.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/group/ResourceManagedExecuteGroupEngine.java
@@ -71,7 +71,7 @@ public abstract class ResourceManagedExecuteGroupEngine
         return result;
     }
     
-    private InputGroup<U> generateSQLExecuteGroup(final String dataSourceName, final List<SQLUnit> sqlUnitGroup, 
+    private InputGroup<U> generateSQLExecuteGroup(final String dataSourceName, final List<SQLUnit> sqlUnitGroup,
                                                   final C connection, final ConnectionMode connectionMode) throws SQLException {
         List<U> result = new LinkedList<>();
         for (SQLUnit each : sqlUnitGroup) {
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/group/StatementExecuteGroupEngine.java b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/group/StatementExecuteGroupEngine.java
index 3d48f67..0ced170 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/group/StatementExecuteGroupEngine.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/main/java/org/apache/shardingsphere/infra/executor/sql/resourced/jdbc/group/StatementExecuteGroupEngine.java
@@ -34,7 +34,7 @@ import java.util.Collection;
  */
 public final class StatementExecuteGroupEngine extends ResourceManagedExecuteGroupEngine<StatementExecuteUnit, JDBCExecutionConnection, Connection, StatementOption> {
     
-    public StatementExecuteGroupEngine(final int maxConnectionsSizePerQuery, 
+    public StatementExecuteGroupEngine(final int maxConnectionsSizePerQuery,
                                        final JDBCExecutionConnection executionConnection, final StatementOption option, final Collection<ShardingSphereRule> rules) {
         super(maxConnectionsSizePerQuery, executionConnection, option, rules);
     }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContextBuilderTest.java b/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContextBuilderTest.java
index 5720e44..1f5c5dc 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContextBuilderTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/context/ExecutionContextBuilderTest.java
@@ -19,13 +19,19 @@ package org.apache.shardingsphere.infra.executor.sql.context;
 
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
 import org.apache.shardingsphere.infra.metadata.datasource.DataSourceMetaDatas;
+import org.apache.shardingsphere.infra.metadata.schema.RuleSchemaMetaData;
 import org.apache.shardingsphere.infra.rewrite.engine.result.GenericSQLRewriteResult;
 import org.apache.shardingsphere.infra.rewrite.engine.result.RouteSQLRewriteResult;
 import org.apache.shardingsphere.infra.rewrite.engine.result.SQLRewriteUnit;
 import org.apache.shardingsphere.infra.route.context.RouteMapper;
 import org.apache.shardingsphere.infra.route.context.RouteUnit;
+import org.apache.shardingsphere.sql.parser.binder.metadata.column.ColumnMetaData;
+import org.apache.shardingsphere.sql.parser.binder.metadata.schema.SchemaMetaData;
+import org.apache.shardingsphere.sql.parser.binder.metadata.table.TableMetaData;
+import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 import org.junit.Test;
 
+import java.sql.Types;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -49,22 +55,23 @@ public final class ExecutionContextBuilderTest {
         DataSourceMetaDatas dataSourceMetaDatas = mock(DataSourceMetaDatas.class);
         String firstDataSourceName = "firstDataSourceName";
         when(dataSourceMetaDatas.getAllInstanceDataSourceNames()).thenReturn(Arrays.asList(firstDataSourceName, "lastDataSourceName"));
-        ShardingSphereMetaData metaData = new ShardingSphereMetaData(dataSourceMetaDatas, null);
-        Collection<ExecutionUnit> actual = ExecutionContextBuilder.build(metaData, genericSQLRewriteResult);
+        ShardingSphereMetaData metaData = new ShardingSphereMetaData(dataSourceMetaDatas, buildRuleSchemaMetaData(), "sharding_db");
+        Collection<ExecutionUnit> actual = ExecutionContextBuilder.build(metaData, genericSQLRewriteResult, mock(SQLStatementContext.class));
         Collection<ExecutionUnit> expected = Collections.singletonList(new ExecutionUnit(firstDataSourceName, new SQLUnit(sql, parameters)));
         assertThat(actual, is(expected));
     }
     
     @Test
     public void assertBuildRouteSQLRewriteResult() {
-        RouteUnit routeUnit1 = new RouteUnit(new RouteMapper("logicName1", "actualName1"), null);
+        RouteUnit routeUnit1 = new RouteUnit(new RouteMapper("logicName1", "actualName1"), Arrays.asList(new RouteMapper("logicName1", "actualName1")));
         SQLRewriteUnit sqlRewriteUnit1 = new SQLRewriteUnit("sql1", Collections.singletonList("parameter1"));
-        RouteUnit routeUnit2 = new RouteUnit(new RouteMapper("logicName2", "actualName2"), null);
+        RouteUnit routeUnit2 = new RouteUnit(new RouteMapper("logicName2", "actualName2"), Arrays.asList(new RouteMapper("logicName1", "actualName1")));
         SQLRewriteUnit sqlRewriteUnit2 = new SQLRewriteUnit("sql2", Collections.singletonList("parameter2"));
         Map<RouteUnit, SQLRewriteUnit> sqlRewriteUnits = new HashMap<>(2, 1);
         sqlRewriteUnits.put(routeUnit1, sqlRewriteUnit1);
         sqlRewriteUnits.put(routeUnit2, sqlRewriteUnit2);
-        Collection<ExecutionUnit> actual = ExecutionContextBuilder.build(null, new RouteSQLRewriteResult(sqlRewriteUnits));
+        ShardingSphereMetaData metaData = new ShardingSphereMetaData(mock(DataSourceMetaDatas.class), buildRuleSchemaMetaData(), "sharding_db");
+        Collection<ExecutionUnit> actual = ExecutionContextBuilder.build(metaData, new RouteSQLRewriteResult(sqlRewriteUnits), mock(SQLStatementContext.class));
         ExecutionUnit expectedUnit1 = new ExecutionUnit("actualName1", new SQLUnit("sql1", Collections.singletonList("parameter1")));
         ExecutionUnit expectedUnit2 = new ExecutionUnit("actualName2", new SQLUnit("sql2", Collections.singletonList("parameter2")));
         Collection<ExecutionUnit> expected = new LinkedHashSet<>();
@@ -72,4 +79,22 @@ public final class ExecutionContextBuilderTest {
         expected.add(expectedUnit2);
         assertThat(actual, is(expected));
     }
+    
+    private RuleSchemaMetaData buildRuleSchemaMetaData() {
+        Map<String, TableMetaData> tableMetaDataMap = new HashMap<>(3, 1);
+        tableMetaDataMap.put("logicName1", new TableMetaData(Arrays.asList(new ColumnMetaData("order_id", Types.INTEGER, "int", true, false, false),
+                new ColumnMetaData("user_id", Types.INTEGER, "int", false, false, false),
+                new ColumnMetaData("status", Types.INTEGER, "int", false, false, false)), Collections.emptySet()));
+        tableMetaDataMap.put("logicName2", new TableMetaData(Arrays.asList(new ColumnMetaData("item_id", Types.INTEGER, "int", true, false, false),
+                new ColumnMetaData("order_id", Types.INTEGER, "int", false, false, false),
+                new ColumnMetaData("user_id", Types.INTEGER, "int", false, false, false),
+                new ColumnMetaData("status", Types.VARCHAR, "varchar", false, false, false),
+                new ColumnMetaData("c_date", Types.TIMESTAMP, "timestamp", false, false, false)), Collections.emptySet()));
+        tableMetaDataMap.put("t_other", new TableMetaData(Collections.singletonList(new ColumnMetaData("order_id", Types.INTEGER, "int", true, false, false)), Collections.emptySet()));
+        Map<String, TableMetaData> unconfiguredTableMetaDataMap = new HashMap<>(1, 1);
+        unconfiguredTableMetaDataMap.put("t_category", new TableMetaData(Collections.singletonList(new ColumnMetaData("order_id", Types.INTEGER, "int", true, false, false)), Collections.emptySet()));
+        Map<String, SchemaMetaData> unconfiguredSchemaMetaDataMap = new HashMap<>(1, 1);
+        unconfiguredSchemaMetaDataMap.put("ds_0", new SchemaMetaData(unconfiguredTableMetaDataMap));
+        return new RuleSchemaMetaData(new SchemaMetaData(tableMetaDataMap), unconfiguredSchemaMetaDataMap);
+    }
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/execute/jdbc/group/PreparedStatementExecuteGroupEngineTest.java b/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/execute/jdbc/group/PreparedStatementExecuteGroupEngineTest.java
index 8597bb5..2321c8d 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/execute/jdbc/group/PreparedStatementExecuteGroupEngineTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/execute/jdbc/group/PreparedStatementExecuteGroupEngineTest.java
@@ -25,6 +25,7 @@ import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.StatementExec
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.connection.JDBCExecutionConnection;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.group.PreparedStatementExecuteGroupEngine;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.group.StatementOption;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -53,7 +54,7 @@ public final class PreparedStatementExecuteGroupEngineTest {
     public void assertGetExecuteUnitGroupForOneShardMemoryStrictly() throws SQLException {
         preparedStatementExecuteGroupEngine = new PreparedStatementExecuteGroupEngine(
                 2, mockExecutionConnection(1, ConnectionMode.MEMORY_STRICTLY), new StatementOption(true), Collections.singletonList(mock(ShardingSphereRule.class)));
-        Collection<InputGroup<StatementExecuteUnit>> actual = preparedStatementExecuteGroupEngine.generate(mockShardRouteUnit(1, 1));
+        Collection<InputGroup<StatementExecuteUnit>> actual = preparedStatementExecuteGroupEngine.generate(mock(RouteContext.class), mockShardRouteUnit(1, 1));
         assertThat(actual.size(), is(1));
         for (InputGroup<StatementExecuteUnit> each : actual) {
             assertThat(each.getInputs().size(), is(1));
@@ -64,7 +65,7 @@ public final class PreparedStatementExecuteGroupEngineTest {
     public void assertGetExecuteUnitGroupForMultiShardConnectionStrictly() throws SQLException {
         preparedStatementExecuteGroupEngine = new PreparedStatementExecuteGroupEngine(
                 1, mockExecutionConnection(1, ConnectionMode.CONNECTION_STRICTLY), new StatementOption(true), Collections.singletonList(mock(ShardingSphereRule.class)));
-        Collection<InputGroup<StatementExecuteUnit>> actual = preparedStatementExecuteGroupEngine.generate(mockShardRouteUnit(10, 2));
+        Collection<InputGroup<StatementExecuteUnit>> actual = preparedStatementExecuteGroupEngine.generate(mock(RouteContext.class), mockShardRouteUnit(10, 2));
         assertThat(actual.size(), is(10));
         for (InputGroup<StatementExecuteUnit> each : actual) {
             assertThat(each.getInputs().size(), is(2));
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/execute/jdbc/group/StatementExecuteGroupEngineTest.java b/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/execute/jdbc/group/StatementExecuteGroupEngineTest.java
index 1bcabb6..43ca5a3 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/execute/jdbc/group/StatementExecuteGroupEngineTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/execute/jdbc/group/StatementExecuteGroupEngineTest.java
@@ -25,6 +25,7 @@ import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.StatementExec
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.connection.JDBCExecutionConnection;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.group.StatementExecuteGroupEngine;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.group.StatementOption;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -53,7 +54,7 @@ public final class StatementExecuteGroupEngineTest {
     public void assertGetExecuteUnitGroupForOneShardMemoryStrictly() throws SQLException {
         executeGroupEngine = new StatementExecuteGroupEngine(
                 2, mockExecutionConnection(1, ConnectionMode.MEMORY_STRICTLY), new StatementOption(true), Collections.singletonList(mock(ShardingSphereRule.class)));
-        Collection<InputGroup<StatementExecuteUnit>> actual = executeGroupEngine.generate(mockShardRouteUnit(1, 1));
+        Collection<InputGroup<StatementExecuteUnit>> actual = executeGroupEngine.generate(mock(RouteContext.class), mockShardRouteUnit(1, 1));
         assertThat(actual.size(), is(1));
         for (InputGroup<StatementExecuteUnit> each : actual) {
             assertThat(each.getInputs().size(), is(1));
@@ -64,7 +65,7 @@ public final class StatementExecuteGroupEngineTest {
     public void assertGetExecuteUnitGroupForMultiShardConnectionStrictly() throws SQLException {
         executeGroupEngine = new StatementExecuteGroupEngine(
                 1, mockExecutionConnection(1, ConnectionMode.CONNECTION_STRICTLY), new StatementOption(true), Collections.singletonList(mock(ShardingSphereRule.class)));
-        Collection<InputGroup<StatementExecuteUnit>> actual = executeGroupEngine.generate(mockShardRouteUnit(10, 2));
+        Collection<InputGroup<StatementExecuteUnit>> actual = executeGroupEngine.generate(mock(RouteContext.class), mockShardRouteUnit(10, 2));
         assertThat(actual.size(), is(10));
         for (InputGroup<StatementExecuteUnit> each : actual) {
             assertThat(each.getInputs().size(), is(2));
diff --git a/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/log/SQLLoggerTest.java b/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/log/SQLLoggerTest.java
index c01006b..f5c1670 100644
--- a/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/log/SQLLoggerTest.java
+++ b/shardingsphere-infra/shardingsphere-infra-executor/src/test/java/org/apache/shardingsphere/infra/executor/sql/log/SQLLoggerTest.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.infra.executor.sql.log;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
 import org.apache.shardingsphere.infra.executor.sql.context.SQLUnit;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -38,6 +39,7 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
 
 @RunWith(MockitoJUnitRunner.class)
 public final class SQLLoggerTest {
@@ -61,7 +63,7 @@ public final class SQLLoggerTest {
     
     @Test
     public void assertLogNormalSQLWithoutParameter() {
-        SQLLogger.logSQL(SQL, false, new ExecutionContext(null, executionUnits));
+        SQLLogger.logSQL(SQL, false, new ExecutionContext(null, executionUnits, mock(RouteContext.class)));
         InOrder inOrder = inOrder(logger);
         inOrder.verify(logger).info("Logic SQL: {}", new Object[]{SQL});
         inOrder.verify(logger).info("SQLStatement: {}", new Object[]{null});
@@ -74,7 +76,7 @@ public final class SQLLoggerTest {
     public void assertLogNormalSQLWithParameters() {
         List<Object> parameters = executionUnits.iterator().next().getSqlUnit().getParameters();
         parameters.add("parameter");
-        SQLLogger.logSQL(SQL, false, new ExecutionContext(null, executionUnits));
+        SQLLogger.logSQL(SQL, false, new ExecutionContext(null, executionUnits, mock(RouteContext.class)));
         InOrder inOrder = inOrder(logger);
         inOrder.verify(logger).info("Logic SQL: {}", new Object[]{SQL});
         inOrder.verify(logger).info("SQLStatement: {}", new Object[]{null});
@@ -85,7 +87,7 @@ public final class SQLLoggerTest {
     
     @Test
     public void assertLogSimpleSQL() {
-        SQLLogger.logSQL(SQL, true, new ExecutionContext(null, executionUnits));
+        SQLLogger.logSQL(SQL, true, new ExecutionContext(null, executionUnits, mock(RouteContext.class)));
         InOrder inOrder = inOrder(logger);
         inOrder.verify(logger).info("Logic SQL: {}", new Object[]{SQL});
         inOrder.verify(logger).info("SQLStatement: {}", new Object[]{null});
diff --git a/shardingsphere-infra/shardingsphere-infra-rewrite/shardingsphere-infra-rewrite-engine/src/main/java/org/apache/shardingsphere/infra/rewrite/SQLRewriteEntry.java b/shardingsphere-infra/shardingsphere-infra-rewrite/shardingsphere-infra-rewrite-engine/src/main/java/org/apache/shardingsphere/infra/rewrite/SQLRewriteEntry.java
index 773468e..1a8400c 100644
--- a/shardingsphere-infra/shardingsphere-infra-rewrite/shardingsphere-infra-rewrite-engine/src/main/java/org/apache/shardingsphere/infra/rewrite/SQLRewriteEntry.java
+++ b/shardingsphere-infra/shardingsphere-infra-rewrite/shardingsphere-infra-rewrite-engine/src/main/java/org/apache/shardingsphere/infra/rewrite/SQLRewriteEntry.java
@@ -24,6 +24,7 @@ import org.apache.shardingsphere.infra.rewrite.engine.GenericSQLRewriteEngine;
 import org.apache.shardingsphere.infra.rewrite.engine.RouteSQLRewriteEngine;
 import org.apache.shardingsphere.infra.rewrite.engine.result.SQLRewriteResult;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.infra.route.context.RouteResult;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
 import org.apache.shardingsphere.infra.spi.order.OrderedSPIRegistry;
@@ -65,8 +66,8 @@ public final class SQLRewriteEntry {
      */
     public SQLRewriteResult rewrite(final String sql, final List<Object> parameters, final RouteContext routeContext) {
         SQLRewriteContext sqlRewriteContext = createSQLRewriteContext(sql, parameters, routeContext);
-        return routeContext.getRouteResult().getRouteUnits().isEmpty()
-                ? new GenericSQLRewriteEngine().rewrite(sqlRewriteContext) : new RouteSQLRewriteEngine().rewrite(sqlRewriteContext, routeContext.getRouteResult());
+        RouteResult routeResult = routeContext.getRouteResult();
+        return routeResult.getRouteUnits().isEmpty() ? new GenericSQLRewriteEngine().rewrite(sqlRewriteContext) : new RouteSQLRewriteEngine().rewrite(sqlRewriteContext, routeResult);
     }
     
     private SQLRewriteContext createSQLRewriteContext(final String sql, final List<Object> parameters, final RouteContext routeContext) {
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/DefaultRouteStageContext.java
similarity index 73%
copy from shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java
copy to shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/DefaultRouteStageContext.java
index 2f4efab..8ae1531 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java
+++ b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/DefaultRouteStageContext.java
@@ -15,19 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.replica.constant;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
+package org.apache.shardingsphere.infra.route.context;
 
 /**
- * Replica order.
+ * Default route stage context.
  */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class ReplicaOrder {
-    
-    /**
-     * Replica order.
-     */
-    public static final int ORDER = 20;
+public final class DefaultRouteStageContext implements RouteStageContext {
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RawGroup.java
similarity index 73%
copy from shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java
copy to shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RawGroup.java
index 2f4efab..8e37aee 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java
+++ b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RawGroup.java
@@ -15,19 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.replica.constant;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
+package org.apache.shardingsphere.infra.route.context;
 
 /**
- * Replica order.
+ * Raw rule group.
  */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class ReplicaOrder {
-    
-    /**
-     * Replica order.
-     */
-    public static final int ORDER = 20;
+public interface RawGroup {
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java
index 17dc764..417ad0c 100644
--- a/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java
+++ b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteContext.java
@@ -19,9 +19,12 @@ package org.apache.shardingsphere.infra.route.context;
 
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Route context.
@@ -35,4 +38,41 @@ public final class RouteContext {
     private final List<Object> parameters;
     
     private final RouteResult routeResult;
+    
+    private final Map<Class<? extends ShardingSphereRule>, RouteStageContext> routeStageContexts = new LinkedHashMap<>();
+    
+    public RouteContext(final RouteContext parent, final RouteResult routeResult, final RouteStageContext nextRouteStageContext, final Class<? extends ShardingSphereRule> ruleType) {
+        this(parent.getSqlStatementContext(), parent.getParameters(), routeResult);
+        addBeforeRouteStageContexts(parent.getRouteStageContexts());
+        addNextRouteStageContext(ruleType, nextRouteStageContext);
+    }
+    
+    /**
+     * Add before route stage context.
+     *
+     * @param beforeRouteStageContexts before route stage contexts
+     */
+    public void addBeforeRouteStageContexts(final Map<Class<? extends ShardingSphereRule>, RouteStageContext> beforeRouteStageContexts) {
+        getRouteStageContexts().putAll(beforeRouteStageContexts);
+    }
+    
+    /**
+     * Add next route stage context.
+     *
+     * @param ruleType rule type
+     * @param nextRouteStageContext next route stage contexts
+     */
+    public void addNextRouteStageContext(final Class<? extends ShardingSphereRule> ruleType, final RouteStageContext nextRouteStageContext) {
+        getRouteStageContexts().put(ruleType, nextRouteStageContext);
+    }
+    
+    /**
+     * Get route stage context by rule type.
+     *
+     * @param ruleType rule type
+     * @return route stage context
+     */
+    public RouteStageContext getRouteStageContext(final Class<? extends ShardingSphereRule> ruleType) {
+        return getRouteStageContexts().get(ruleType);
+    }
 }
diff --git a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteStageContext.java
similarity index 73%
copy from shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java
copy to shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteStageContext.java
index 2f4efab..787c01b 100644
--- a/shardingsphere-features/shardingsphere-replica/shardingsphere-replica-common/src/main/java/org/apache/shardingsphere/replica/constant/ReplicaOrder.java
+++ b/shardingsphere-infra/shardingsphere-infra-route/src/main/java/org/apache/shardingsphere/infra/route/context/RouteStageContext.java
@@ -15,19 +15,10 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.replica.constant;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
+package org.apache.shardingsphere.infra.route.context;
 
 /**
- * Replica order.
+ * Route stage context.
  */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class ReplicaOrder {
-    
-    /**
-     * Replica order.
-     */
-    public static final int ORDER = 20;
+public interface RouteStageContext {
 }
diff --git a/shardingsphere-infra/shardingsphere-infra-route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decorator/RouteDecoratorFixture.java b/shardingsphere-infra/shardingsphere-infra-route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decorator/RouteDecoratorFixture.java
index d753a00..d250d7a 100644
--- a/shardingsphere-infra/shardingsphere-infra-route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decorator/RouteDecoratorFixture.java
+++ b/shardingsphere-infra/shardingsphere-infra-route/src/test/java/org/apache/shardingsphere/infra/route/fixture/decorator/RouteDecoratorFixture.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.infra.route.fixture.decorator;
 
 import org.apache.shardingsphere.infra.config.properties.ConfigurationProperties;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import org.apache.shardingsphere.infra.route.context.DefaultRouteStageContext;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.route.context.RouteMapper;
 import org.apache.shardingsphere.infra.route.context.RouteResult;
@@ -34,7 +35,7 @@ public final class RouteDecoratorFixture implements RouteDecorator<RouteRuleFixt
     public RouteContext decorate(final RouteContext routeContext, final ShardingSphereMetaData metaData, final RouteRuleFixture rule, final ConfigurationProperties props) {
         RouteResult routeResult = new RouteResult();
         routeResult.getRouteUnits().add(new RouteUnit(new RouteMapper("ds", "ds_0"), Collections.emptyList()));
-        return new RouteContext(routeContext.getSqlStatementContext(), routeContext.getParameters(), routeResult);
+        return new RouteContext(routeContext, routeResult, new DefaultRouteStageContext(), getTypeClass());
     }
     
     @Override
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
index eebe979..c0773dd 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
@@ -37,6 +37,7 @@ import org.apache.shardingsphere.infra.executor.sql.ExecutorConstant;
 import org.apache.shardingsphere.infra.executor.sql.QueryResult;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContextBuilder;
+import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
 import org.apache.shardingsphere.infra.executor.sql.log.SQLLogger;
 import org.apache.shardingsphere.infra.executor.sql.raw.RawSQLExecuteUnit;
 import org.apache.shardingsphere.infra.executor.sql.raw.execute.RawJDBCExecutor;
@@ -55,6 +56,7 @@ import org.apache.shardingsphere.infra.route.DataNodeRouter;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.rule.DataNodeRoutedRule;
 import org.apache.shardingsphere.sql.parser.binder.segment.insert.keygen.GeneratedKeyContext;
+import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.sql.parser.binder.statement.dml.InsertStatementContext;
 import org.apache.shardingsphere.sql.parser.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
@@ -206,13 +208,14 @@ public final class ShardingSpherePreparedStatement extends AbstractPreparedState
     
     private Collection<InputGroup<StatementExecuteUnit>> getInputGroups() throws SQLException {
         int maxConnectionsSizePerQuery = schemaContexts.getProps().<Integer>getValue(ConfigurationPropertyKey.MAX_CONNECTIONS_SIZE_PER_QUERY);
-        return new PreparedStatementExecuteGroupEngine(maxConnectionsSizePerQuery, connection, statementOption, 
-                schemaContexts.getDefaultSchemaContext().getSchema().getRules()).generate(executionContext.getExecutionUnits());
+        return new PreparedStatementExecuteGroupEngine(maxConnectionsSizePerQuery, connection, statementOption,
+                schemaContexts.getDefaultSchemaContext().getSchema().getRules()).generate(executionContext.getRouteContext(), executionContext.getExecutionUnits());
     }
     
     private Collection<InputGroup<RawSQLExecuteUnit>> getRawInputGroups() throws SQLException {
         int maxConnectionsSizePerQuery = schemaContexts.getProps().<Integer>getValue(ConfigurationPropertyKey.MAX_CONNECTIONS_SIZE_PER_QUERY);
-        return new RawExecuteGroupEngine(maxConnectionsSizePerQuery, schemaContexts.getDefaultSchemaContext().getSchema().getRules()).generate(executionContext.getExecutionUnits());
+        return new RawExecuteGroupEngine(maxConnectionsSizePerQuery, schemaContexts.getDefaultSchemaContext().getSchema().getRules())
+                .generate(executionContext.getRouteContext(), executionContext.getExecutionUnits());
     }
     
     @Override
@@ -256,11 +259,14 @@ public final class ShardingSpherePreparedStatement extends AbstractPreparedState
     
     private ExecutionContext createExecutionContext() {
         SchemaContext schemaContext = schemaContexts.getDefaultSchemaContext();
-        RouteContext routeContext = 
-                new DataNodeRouter(schemaContext.getSchema().getMetaData(), schemaContexts.getProps(), schemaContext.getSchema().getRules()).route(sqlStatement, sql, getParameters());
-        SQLRewriteResult sqlRewriteResult = new SQLRewriteEntry(schemaContext.getSchema().getMetaData().getRuleSchemaMetaData().getConfiguredSchemaMetaData(), 
-                schemaContexts.getProps(), schemaContext.getSchema().getRules()).rewrite(sql, new ArrayList<>(getParameters()), routeContext);
-        ExecutionContext result = new ExecutionContext(routeContext.getSqlStatementContext(), ExecutionContextBuilder.build(schemaContext.getSchema().getMetaData(), sqlRewriteResult));
+        DataNodeRouter dataNodeRouter = new DataNodeRouter(schemaContext.getSchema().getMetaData(), schemaContexts.getProps(), schemaContext.getSchema().getRules());
+        RouteContext routeContext = dataNodeRouter.route(sqlStatement, sql, getParameters());
+        SQLRewriteEntry sqlRewriteEntry = new SQLRewriteEntry(schemaContext.getSchema().getMetaData().getRuleSchemaMetaData().getConfiguredSchemaMetaData(),
+                schemaContexts.getProps(), schemaContext.getSchema().getRules());
+        SQLRewriteResult sqlRewriteResult = sqlRewriteEntry.rewrite(sql, new ArrayList<>(getParameters()), routeContext);
+        SQLStatementContext<?> sqlStatementContext = routeContext.getSqlStatementContext();
+        Collection<ExecutionUnit> executionUnits = ExecutionContextBuilder.build(schemaContext.getSchema().getMetaData(), sqlRewriteResult, sqlStatementContext);
+        ExecutionContext result = new ExecutionContext(sqlStatementContext, executionUnits, routeContext);
         findGeneratedKey(result).ifPresent(generatedKey -> generatedValues.add(generatedKey.getGeneratedValues().getLast()));
         logSQL(result);
         return result;
@@ -347,9 +353,9 @@ public final class ShardingSpherePreparedStatement extends AbstractPreparedState
     
     private void initBatchPreparedStatementExecutor() throws SQLException {
         PreparedStatementExecuteGroupEngine executeGroupEngine = new PreparedStatementExecuteGroupEngine(
-                schemaContexts.getProps().<Integer>getValue(ConfigurationPropertyKey.MAX_CONNECTIONS_SIZE_PER_QUERY), 
+                schemaContexts.getProps().<Integer>getValue(ConfigurationPropertyKey.MAX_CONNECTIONS_SIZE_PER_QUERY),
                 connection, statementOption, schemaContexts.getDefaultSchemaContext().getSchema().getRules());
-        batchPreparedStatementExecutor.init(executeGroupEngine.generate(
+        batchPreparedStatementExecutor.init(executeGroupEngine.generate(executionContext.getRouteContext(),
                 new ArrayList<>(batchPreparedStatementExecutor.getBatchExecutionUnits()).stream().map(BatchExecutionUnit::getExecutionUnit).collect(Collectors.toList())));
         setBatchParametersForStatements();
     }
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
index 26accfa..e56ec0d 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
@@ -35,6 +35,7 @@ import org.apache.shardingsphere.infra.executor.sql.ExecutorConstant;
 import org.apache.shardingsphere.infra.executor.sql.QueryResult;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContextBuilder;
+import org.apache.shardingsphere.infra.executor.sql.context.ExecutionUnit;
 import org.apache.shardingsphere.infra.executor.sql.log.SQLLogger;
 import org.apache.shardingsphere.infra.executor.sql.raw.RawSQLExecuteUnit;
 import org.apache.shardingsphere.infra.executor.sql.raw.execute.RawJDBCExecutor;
@@ -53,6 +54,7 @@ import org.apache.shardingsphere.infra.route.DataNodeRouter;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.rule.DataNodeRoutedRule;
 import org.apache.shardingsphere.sql.parser.binder.segment.insert.keygen.GeneratedKeyContext;
+import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.sql.parser.binder.statement.dml.InsertStatementContext;
 import org.apache.shardingsphere.sql.parser.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
@@ -283,11 +285,14 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
         clearStatements();
         SchemaContext schemaContext = schemaContexts.getDefaultSchemaContext();
         SQLStatement sqlStatement = schemaContext.getRuntimeContext().getSqlParserEngine().parse(sql, false);
-        RouteContext routeContext = new DataNodeRouter(
-                schemaContext.getSchema().getMetaData(), schemaContexts.getProps(), schemaContext.getSchema().getRules()).route(sqlStatement, sql, Collections.emptyList());
-        SQLRewriteResult sqlRewriteResult = new SQLRewriteEntry(schemaContext.getSchema().getMetaData().getRuleSchemaMetaData().getConfiguredSchemaMetaData(),
-                schemaContexts.getProps(), schemaContext.getSchema().getRules()).rewrite(sql, Collections.emptyList(), routeContext);
-        ExecutionContext result = new ExecutionContext(routeContext.getSqlStatementContext(), ExecutionContextBuilder.build(schemaContext.getSchema().getMetaData(), sqlRewriteResult));
+        DataNodeRouter dataNodeRouter = new DataNodeRouter(schemaContext.getSchema().getMetaData(), schemaContexts.getProps(), schemaContext.getSchema().getRules());
+        RouteContext routeContext = dataNodeRouter.route(sqlStatement, sql, Collections.emptyList());
+        SQLRewriteEntry sqlRewriteEntry = new SQLRewriteEntry(schemaContext.getSchema().getMetaData().getRuleSchemaMetaData().getConfiguredSchemaMetaData(),
+                schemaContexts.getProps(), schemaContext.getSchema().getRules());
+        SQLRewriteResult sqlRewriteResult = sqlRewriteEntry.rewrite(sql, Collections.emptyList(), routeContext);
+        SQLStatementContext<?> sqlStatementContext = routeContext.getSqlStatementContext();
+        Collection<ExecutionUnit> executionUnits = ExecutionContextBuilder.build(schemaContext.getSchema().getMetaData(), sqlRewriteResult, sqlStatementContext);
+        ExecutionContext result = new ExecutionContext(sqlStatementContext, executionUnits, routeContext);
         logSQL(sql, schemaContexts.getProps(), result);
         return result;
     }
@@ -307,13 +312,14 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
     
     private Collection<InputGroup<StatementExecuteUnit>> getInputGroups() throws SQLException {
         int maxConnectionsSizePerQuery = schemaContexts.getProps().<Integer>getValue(ConfigurationPropertyKey.MAX_CONNECTIONS_SIZE_PER_QUERY);
-        return new StatementExecuteGroupEngine(maxConnectionsSizePerQuery, connection, statementOption, 
-                schemaContexts.getDefaultSchemaContext().getSchema().getRules()).generate(executionContext.getExecutionUnits());
+        return new StatementExecuteGroupEngine(maxConnectionsSizePerQuery, connection, statementOption,
+                schemaContexts.getDefaultSchemaContext().getSchema().getRules()).generate(executionContext.getRouteContext(), executionContext.getExecutionUnits());
     }
     
     private Collection<InputGroup<RawSQLExecuteUnit>> getRawInputGroups() throws SQLException {
         int maxConnectionsSizePerQuery = schemaContexts.getProps().<Integer>getValue(ConfigurationPropertyKey.MAX_CONNECTIONS_SIZE_PER_QUERY);
-        return new RawExecuteGroupEngine(maxConnectionsSizePerQuery, schemaContexts.getDefaultSchemaContext().getSchema().getRules()).generate(executionContext.getExecutionUnits());
+        return new RawExecuteGroupEngine(maxConnectionsSizePerQuery, schemaContexts.getDefaultSchemaContext().getSchema().getRules())
+                .generate(executionContext.getRouteContext(), executionContext.getExecutionUnits());
     }
     
     private void cacheStatements(final Collection<InputGroup<StatementExecuteUnit>> inputGroups) {
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutorTest.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutorTest.java
index 5be2076..693999b 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutorTest.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/PreparedStatementExecutorTest.java
@@ -247,8 +247,8 @@ public final class PreparedStatementExecutorTest extends AbstractBaseExecutorTes
         List<StatementExecuteUnit> preparedStatementExecuteUnits = new LinkedList<>();
         result.add(new InputGroup<>(preparedStatementExecuteUnits));
         for (PreparedStatement each : preparedStatements) {
-            preparedStatementExecuteUnits.add(
-                    new StatementExecuteUnit(new ExecutionUnit("ds_0", new SQLUnit(isQuery ? DQL_SQL : DML_SQL, Collections.singletonList(1))), ConnectionMode.MEMORY_STRICTLY, each));
+            preparedStatementExecuteUnits.add(new StatementExecuteUnit(new ExecutionUnit("ds_0", new SQLUnit(isQuery ? DQL_SQL : DML_SQL, Collections.singletonList(1))),
+                    ConnectionMode.MEMORY_STRICTLY, each));
         }
         return result;
     }
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/StatementExecutorTest.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/StatementExecutorTest.java
index acc1b72..515ae54 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/StatementExecutorTest.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/StatementExecutorTest.java
@@ -311,7 +311,8 @@ public final class StatementExecutorTest extends AbstractBaseExecutorTest {
         result.add(new InputGroup<>(statementExecuteUnits));
         for (Statement each : statements) {
             statementExecuteUnits.add(
-                    new StatementExecuteUnit(new ExecutionUnit("ds_0", new SQLUnit(isQuery ? DQL_SQL : DML_SQL, Collections.singletonList(1))), ConnectionMode.MEMORY_STRICTLY, each));
+                    new StatementExecuteUnit(new ExecutionUnit("ds_0", new SQLUnit(isQuery ? DQL_SQL : DML_SQL, Collections.singletonList(1))),
+                            ConnectionMode.MEMORY_STRICTLY, each));
         }
         return result;
     }
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/batch/BatchExecutionUnitTest.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/batch/BatchExecutionUnitTest.java
index 77d111c..58c9697 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/batch/BatchExecutionUnitTest.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/batch/BatchExecutionUnitTest.java
@@ -56,8 +56,11 @@ public final class BatchExecutionUnitTest {
     
     @Test
     public void assertToString() {
-        BatchExecutionUnit actual = new BatchExecutionUnit(new ExecutionUnit(DATA_SOURCE_NAME, new SQLUnit(SQL, Lists.newArrayList(1))));
+        ExecutionUnit executionUnit = new ExecutionUnit(DATA_SOURCE_NAME, new SQLUnit(SQL, Lists.newArrayList(1)));
+        BatchExecutionUnit actual = new BatchExecutionUnit(executionUnit);
         assertThat(actual.toString(), is(String.format("BatchExecutionUnit(executionUnit=ExecutionUnit"
-                + "(dataSourceName=%s, sqlUnit=SQLUnit(sql=%s, parameters=[%d])), jdbcAndActualAddBatchCallTimesMap={}, actualCallAddBatchTimes=0)", DATA_SOURCE_NAME, SQL, 1)));
+                + "(dataSourceName=%s, sqlUnit=SQLUnit(sql=%s, parameters=[%d], "
+                + "sqlRuntimeContext=SQLRuntimeContext(schemaName=%s, logicTables=[], actualTables=[], primaryKeyMetaDatas=[], readOnly=false))), "
+                + "jdbcAndActualAddBatchCallTimesMap={}, actualCallAddBatchTimes=0)", DATA_SOURCE_NAME, SQL, 1, "null")));
     }
 }
diff --git a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/batch/BatchPreparedStatementExecutorTest.java b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/batch/BatchPreparedStatementExecutorTest.java
index 5946936..a7ffc3b 100644
--- a/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/batch/BatchPreparedStatementExecutorTest.java
+++ b/shardingsphere-jdbc/shardingsphere-jdbc-core/src/test/java/org/apache/shardingsphere/driver/executor/batch/BatchPreparedStatementExecutorTest.java
@@ -136,7 +136,8 @@ public final class BatchPreparedStatementExecutorTest extends AbstractBaseExecut
             batchExecutionUnit.mapAddBatchCount(0);
             batchExecutionUnit.mapAddBatchCount(1);
             batchExecutionUnits.add(batchExecutionUnit);
-            preparedStatementExecuteUnits.add(new StatementExecuteUnit(new ExecutionUnit("ds_0", new SQLUnit(SQL, Collections.singletonList(1))), ConnectionMode.MEMORY_STRICTLY, each));
+            preparedStatementExecuteUnits.add(new StatementExecuteUnit(new ExecutionUnit("ds_0", new SQLUnit(SQL, Collections.singletonList(1))),
+                    ConnectionMode.MEMORY_STRICTLY, each));
         }
         setFields(executeGroups, batchExecutionUnits);
     }
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/execute/engine/jdbc/JDBCExecuteEngine.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/execute/engine/jdbc/JDBCExecuteEngine.java
index e2c408b..81e518c 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/execute/engine/jdbc/JDBCExecuteEngine.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/execute/engine/jdbc/JDBCExecuteEngine.java
@@ -35,6 +35,7 @@ import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.StatementExec
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.ExecutorExceptionHandler;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.executor.SQLExecutor;
 import org.apache.shardingsphere.infra.executor.sql.resourced.jdbc.group.StatementOption;
+import org.apache.shardingsphere.infra.route.context.RouteContext;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
 import org.apache.shardingsphere.proxy.backend.communication.jdbc.execute.SQLExecuteEngine;
@@ -105,24 +106,25 @@ public final class JDBCExecuteEngine implements SQLExecuteEngine {
                 : executeWithUnmanagedResource(executionContext, maxConnectionsSizePerQuery);
     }
     
-    private Collection<ExecuteResult> executeWithManagedResource(final ExecutionContext executionContext, 
+    private Collection<ExecuteResult> executeWithManagedResource(final ExecutionContext executionContext,
                                                                  final int maxConnectionsSizePerQuery, final boolean isReturnGeneratedKeys, final boolean isExceptionThrown) throws SQLException {
         DatabaseType databaseType = ProxyContext.getInstance().getSchemaContexts().getDatabaseType();
-        return sqlExecutor.execute(generateInputGroups(executionContext.getExecutionUnits(), maxConnectionsSizePerQuery, isReturnGeneratedKeys),
+        return sqlExecutor.execute(generateInputGroups(executionContext.getExecutionUnits(), maxConnectionsSizePerQuery, isReturnGeneratedKeys, executionContext.getRouteContext()),
                 new ProxySQLExecutorCallback(databaseType, executionContext.getSqlStatementContext(), backendConnection, jdbcExecutorWrapper, isExceptionThrown, isReturnGeneratedKeys, true),
                 new ProxySQLExecutorCallback(databaseType, executionContext.getSqlStatementContext(), backendConnection, jdbcExecutorWrapper, isExceptionThrown, isReturnGeneratedKeys, false));
     }
     
     @SuppressWarnings({"unchecked", "rawtypes"})
-    private Collection<InputGroup<StatementExecuteUnit>> generateInputGroups(final Collection<ExecutionUnit> executionUnits, 
-                                                                             final int maxConnectionsSizePerQuery, final boolean isReturnGeneratedKeys) throws SQLException {
+    private Collection<InputGroup<StatementExecuteUnit>> generateInputGroups(final Collection<ExecutionUnit> executionUnits, final int maxConnectionsSizePerQuery, final boolean isReturnGeneratedKeys,
+                                                                             final RouteContext routeContext) throws SQLException {
         ExecuteGroupEngine executeGroupEngine = jdbcExecutorWrapper.getExecuteGroupEngine(backendConnection, maxConnectionsSizePerQuery, new StatementOption(isReturnGeneratedKeys));
-        return (Collection<InputGroup<StatementExecuteUnit>>) executeGroupEngine.generate(executionUnits);
+        return (Collection<InputGroup<StatementExecuteUnit>>) executeGroupEngine.generate(routeContext, executionUnits);
     }
     
     private Collection<ExecuteResult> executeWithUnmanagedResource(final ExecutionContext executionContext, final int maxConnectionsSizePerQuery) throws SQLException {
         Collection<ShardingSphereRule> rules = ProxyContext.getInstance().getSchema(backendConnection.getSchemaName()).getSchema().getRules();
-        Collection<InputGroup<RawSQLExecuteUnit>> inputGroups = new RawExecuteGroupEngine(maxConnectionsSizePerQuery, rules).generate(executionContext.getExecutionUnits());
+        Collection<InputGroup<RawSQLExecuteUnit>> inputGroups = new RawExecuteGroupEngine(maxConnectionsSizePerQuery, rules).generate(executionContext.getRouteContext(),
+                executionContext.getExecutionUnits());
         // TODO handle query header
         return rawExecutor.execute(inputGroups, new RawSQLExecutorCallback());
     }
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/wrapper/PreparedStatementExecutorWrapper.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/wrapper/PreparedStatementExecutorWrapper.java
index ece4c02..d1aa221 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/wrapper/PreparedStatementExecutorWrapper.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/wrapper/PreparedStatementExecutorWrapper.java
@@ -30,10 +30,12 @@ import org.apache.shardingsphere.infra.rewrite.SQLRewriteEntry;
 import org.apache.shardingsphere.infra.rewrite.engine.result.SQLRewriteResult;
 import org.apache.shardingsphere.infra.route.DataNodeRouter;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.infra.route.context.RouteResult;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.sql.parser.binder.statement.CommonSQLStatementContext;
+import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 
 import java.sql.PreparedStatement;
@@ -62,14 +64,18 @@ public final class PreparedStatementExecutorWrapper implements JDBCExecutorWrapp
     public ExecutionContext generateExecutionContext(final String sql) {
         Collection<ShardingSphereRule> rules = schema.getSchema().getRules();
         if (rules.isEmpty()) {
-            return new ExecutionContext(
-                    new CommonSQLStatementContext(sqlStatement), new ExecutionUnit(schema.getSchema().getDataSources().keySet().iterator().next(), new SQLUnit(sql, parameters)));
+            SQLStatementContext<?> sqlStatementContext = new CommonSQLStatementContext(sqlStatement);
+            return new ExecutionContext(sqlStatementContext, new ExecutionUnit(schema.getSchema().getDataSources().keySet().iterator().next(), new SQLUnit(sql, parameters)),
+                    new RouteContext(sqlStatementContext, parameters, new RouteResult()));
         }
-        RouteContext routeContext = new DataNodeRouter(schema.getSchema().getMetaData(), PROXY_SCHEMA_CONTEXTS.getSchemaContexts().getProps(), rules).route(sqlStatement, sql, parameters);
-        SQLRewriteEntry sqlRewriteEntry = new SQLRewriteEntry(schema.getSchema().getMetaData().getRuleSchemaMetaData().getConfiguredSchemaMetaData(), 
+        DataNodeRouter dataNodeRouter = new DataNodeRouter(schema.getSchema().getMetaData(), PROXY_SCHEMA_CONTEXTS.getSchemaContexts().getProps(), rules);
+        RouteContext routeContext = dataNodeRouter.route(sqlStatement, sql, parameters);
+        SQLRewriteEntry sqlRewriteEntry = new SQLRewriteEntry(schema.getSchema().getMetaData().getRuleSchemaMetaData().getConfiguredSchemaMetaData(),
                 PROXY_SCHEMA_CONTEXTS.getSchemaContexts().getProps(), rules);
         SQLRewriteResult sqlRewriteResult = sqlRewriteEntry.rewrite(sql, new ArrayList<>(parameters), routeContext);
-        return new ExecutionContext(routeContext.getSqlStatementContext(), ExecutionContextBuilder.build(schema.getSchema().getMetaData(), sqlRewriteResult));
+        SQLStatementContext<?> sqlStatementContext = routeContext.getSqlStatementContext();
+        Collection<ExecutionUnit> executionUnits = ExecutionContextBuilder.build(schema.getSchema().getMetaData(), sqlRewriteResult, sqlStatementContext);
+        return new ExecutionContext(sqlStatementContext, executionUnits, routeContext);
     }
     
     @Override
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/wrapper/StatementExecutorWrapper.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/wrapper/StatementExecutorWrapper.java
index 00b1426..51054a1 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/wrapper/StatementExecutorWrapper.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/communication/jdbc/wrapper/StatementExecutorWrapper.java
@@ -29,10 +29,12 @@ import org.apache.shardingsphere.infra.rewrite.SQLRewriteEntry;
 import org.apache.shardingsphere.infra.rewrite.engine.result.SQLRewriteResult;
 import org.apache.shardingsphere.infra.route.DataNodeRouter;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.infra.route.context.RouteResult;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.proxy.backend.communication.jdbc.connection.BackendConnection;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.sql.parser.binder.statement.CommonSQLStatementContext;
+import org.apache.shardingsphere.sql.parser.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 
 import java.sql.SQLException;
@@ -62,7 +64,9 @@ public final class StatementExecutorWrapper implements JDBCExecutorWrapper {
         RouteContext routeContext = router.route(sqlStatement, sql, Collections.emptyList());
         SQLRewriteResult sqlRewriteResult = new SQLRewriteEntry(schema.getSchema().getMetaData().getRuleSchemaMetaData().getConfiguredSchemaMetaData(),
                 PROXY_SCHEMA_CONTEXTS.getSchemaContexts().getProps(), rules).rewrite(sql, Collections.emptyList(), routeContext);
-        return new ExecutionContext(routeContext.getSqlStatementContext(), ExecutionContextBuilder.build(schema.getSchema().getMetaData(), sqlRewriteResult));
+        SQLStatementContext<?> sqlStatementContext = routeContext.getSqlStatementContext();
+        Collection<ExecutionUnit> executionUnits = ExecutionContextBuilder.build(schema.getSchema().getMetaData(), sqlRewriteResult, sqlStatementContext);
+        return new ExecutionContext(sqlStatementContext, executionUnits, routeContext);
     }
     
     @Override
@@ -78,6 +82,8 @@ public final class StatementExecutorWrapper implements JDBCExecutorWrapper {
     @SuppressWarnings("unchecked")
     private ExecutionContext createExecutionContext(final String sql) {
         String dataSource = schema.getSchema().getDataSources().isEmpty() ? "" : schema.getSchema().getDataSources().keySet().iterator().next();
-        return new ExecutionContext(new CommonSQLStatementContext(sqlStatement), new ExecutionUnit(dataSource, new SQLUnit(sql, Collections.emptyList())));
+        SQLStatementContext<?> sqlStatementContext = new CommonSQLStatementContext(sqlStatement);
+        ExecutionUnit executionUnit = new ExecutionUnit(dataSource, new SQLUnit(sql, Collections.emptyList()));
+        return new ExecutionContext(sqlStatementContext, executionUnit, new RouteContext(sqlStatementContext, Collections.emptyList(), new RouteResult()));
     }
 }
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/sctl/hint/ShardingCTLHintBackendHandlerTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/sctl/hint/ShardingCTLHintBackendHandlerTest.java
index 5205379..e9ad215 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/sctl/hint/ShardingCTLHintBackendHandlerTest.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/sctl/hint/ShardingCTLHintBackendHandlerTest.java
@@ -208,7 +208,8 @@ public final class ShardingCTLHintBackendHandlerTest {
         ShardingSphereSchema shardingSphereSchema = mock(ShardingSphereSchema.class);
         when(result.getSchema()).thenReturn(shardingSphereSchema);
         when(shardingSphereSchema.getMetaData()).thenReturn(
-                new ShardingSphereMetaData(mock(DataSourceMetaDatas.class), new RuleSchemaMetaData(new SchemaMetaData(ImmutableMap.of("user", mock(TableMetaData.class))), Collections.emptyMap())));
+                new ShardingSphereMetaData(mock(DataSourceMetaDatas.class), new RuleSchemaMetaData(new SchemaMetaData(ImmutableMap.of("user", mock(TableMetaData.class))), Collections.emptyMap()),
+                        "sharding_db"));
         return Collections.singletonMap("schema", result);
     }
     
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/SQLStatementContext.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/SQLStatementContext.java
index 2f5e7c9..8538262 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/SQLStatementContext.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-binder/src/main/java/org/apache/shardingsphere/sql/parser/binder/statement/SQLStatementContext.java
@@ -19,6 +19,7 @@ package org.apache.shardingsphere.sql.parser.binder.statement;
 
 import org.apache.shardingsphere.sql.parser.binder.segment.table.TablesContext;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.util.SQLUtil;
 
 /**
  * SQL statement context.
@@ -40,4 +41,13 @@ public interface SQLStatementContext<T extends SQLStatement> {
      * @return tables context
      */
     TablesContext getTablesContext();
+    
+    /**
+     * Determine whether SQL is read-only.
+     *
+     * @return true if read-only, otherwise false
+     */
+    default boolean isReadOnly() {
+        return SQLUtil.isReadOnly(getSqlStatement());
+    }
 }
diff --git a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtil.java b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtil.java
index 81f571f..f0a1596 100644
--- a/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtil.java
+++ b/shardingsphere-sql-parser/shardingsphere-sql-parser-statement/src/main/java/org/apache/shardingsphere/sql/parser/sql/common/util/SQLUtil.java
@@ -22,6 +22,37 @@ import com.google.common.base.Strings;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.apache.shardingsphere.sql.parser.sql.common.constant.Paren;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.DALStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dcl.DCLStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dcl.GrantStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dcl.RevokeStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterIndexStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.AlterTableStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateIndexStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.CreateTableStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DDLStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropIndexStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.DropTableStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.ddl.TruncateStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DeleteStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.InsertStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.UpdateStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLCacheIndexStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLChecksumTableStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLFlushStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLInstallPluginStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLKillStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLLoadIndexInfoStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLOptimizeTableStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLRepairTableStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLResetStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLUninstallPluginStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLUseStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.sqlserver.dcl.SQLServerDenyUserStatement;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
@@ -103,4 +134,78 @@ public final class SQLUtil {
         }
         return result;
     }
+    
+    /**
+     * Determine whether SQL is read-only.
+     *
+     * @param sqlStatement SQL statement
+     * @return true if read-only, otherwise false
+     */
+    public static boolean isReadOnly(final SQLStatement sqlStatement) {
+        if (sqlStatement instanceof DMLStatement) {
+            return isReadOnly((DMLStatement) sqlStatement);
+        }
+        if (sqlStatement instanceof DDLStatement) {
+            return isReadOnly((DDLStatement) sqlStatement);
+        }
+        if (sqlStatement instanceof DCLStatement) {
+            return isReadOnly((DCLStatement) sqlStatement);
+        }
+        if (sqlStatement instanceof DALStatement) {
+            return isReadOnly((DALStatement) sqlStatement);
+        }
+        throw new UnsupportedOperationException(String.format("Unsupported SQL Type `%s`", sqlStatement.getClass().getSimpleName()));
+    }
+    
+    private static boolean isReadOnly(final DMLStatement sqlStatement) {
+        if (sqlStatement instanceof SelectStatement) {
+            return true;
+        } else if (sqlStatement instanceof UpdateStatement
+                | sqlStatement instanceof DeleteStatement
+                | sqlStatement instanceof InsertStatement) {
+            return false;
+        }
+        throw new UnsupportedOperationException(String.format("Unsupported SQL Type `%s`", sqlStatement.getClass().getSimpleName()));
+    }
+    
+    private static boolean isReadOnly(final DDLStatement sqlStatement) {
+        if (sqlStatement instanceof CreateTableStatement
+                | sqlStatement instanceof AlterTableStatement
+                | sqlStatement instanceof DropTableStatement
+                | sqlStatement instanceof CreateIndexStatement
+                | sqlStatement instanceof AlterIndexStatement
+                | sqlStatement instanceof DropIndexStatement
+                | sqlStatement instanceof TruncateStatement
+                | sqlStatement instanceof AlterTableStatement) {
+            return false;
+        }
+        return false;
+    }
+    
+    private static boolean isReadOnly(final DCLStatement sqlStatement) {
+        if (sqlStatement instanceof GrantStatement
+                | sqlStatement instanceof RevokeStatement
+                | sqlStatement instanceof SQLServerDenyUserStatement) {
+            return false;
+        }
+        return false;
+    }
+    
+    private static boolean isReadOnly(final DALStatement sqlStatement) {
+        if (sqlStatement instanceof SetStatement
+                | sqlStatement instanceof MySQLUseStatement
+                | sqlStatement instanceof MySQLUninstallPluginStatement
+                | sqlStatement instanceof MySQLResetStatement
+                | sqlStatement instanceof MySQLRepairTableStatement
+                | sqlStatement instanceof MySQLOptimizeTableStatement
+                | sqlStatement instanceof MySQLLoadIndexInfoStatement
+                | sqlStatement instanceof MySQLKillStatement
+                | sqlStatement instanceof MySQLInstallPluginStatement
+                | sqlStatement instanceof MySQLFlushStatement
+                | sqlStatement instanceof MySQLChecksumTableStatement
+                | sqlStatement instanceof MySQLCacheIndexStatement) {
+            return false;
+        }
+        return true;
+    }
 }