You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by pa...@apache.org on 2023/06/13 01:34:22 UTC

[shardingsphere] branch master updated: Add new SQLFederationEngine to handle sql decide, compile and execute (#26309)

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

panjuan 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 dc52a949dba Add new SQLFederationEngine to handle sql decide, compile and execute (#26309)
dc52a949dba is described below

commit dc52a949dbaa44c2b11182c91ac296206e1bd63e
Author: Zhengqiang Duan <du...@apache.org>
AuthorDate: Tue Jun 13 09:34:12 2023 +0800

    Add new SQLFederationEngine to handle sql decide, compile and execute (#26309)
    
    * Add new SQLFederationEngine to handle sql decide, compile and execute
    
    * fix unit test
    
    * fix checkstyle
---
 .../driver/executor/DriverExecutor.java            |  17 +--
 .../statement/ShardingSpherePreparedStatement.java |   7 +-
 .../core/statement/ShardingSphereStatement.java    |   7 +-
 .../decider/SQLFederationDecideEngine.java         |  84 -----------
 .../SQLFederationEngine.java}                      | 161 ++++++++++++---------
 .../optimizer/SQLFederationCompilerEngine.java     |  49 +++++++
 .../planner/cache/ExecutionPlanCacheBuilder.java   |  46 ++++++
 .../planner/cache/ExecutionPlanCacheLoader.java    |  43 ++++++
 .../sqlfederation/rule/SQLFederationRule.java      |   4 -
 .../SQLFederationEngineTest.java}                  | 105 ++++++++------
 .../decider/SQLFederationDeciderMatchFixture.java  |   4 +-
 .../SQLFederationDeciderNotMatchFixture.java       |   4 +-
 .../rule/SQLFederationDeciderRuleMatchFixture.java |   2 +-
 .../SQLFederationDeciderRuleNotMatchFixture.java   |   2 +-
 ...ngsphere.sqlfederation.spi.SQLFederationDecider |   4 +-
 .../proxy/backend/connector/DatabaseConnector.java |  35 +----
 .../proxy/backend/connector/ProxySQLExecutor.java  |  26 +++-
 .../handler/distsql/rul/sql/PreviewExecutor.java   |  29 ++--
 .../backend/connector/DatabaseConnectorTest.java   |  39 -----
 .../backend/connector/ProxySQLExecutorTest.java    |  48 ++++--
 20 files changed, 389 insertions(+), 327 deletions(-)

diff --git a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/executor/DriverExecutor.java b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/executor/DriverExecutor.java
index 8f651b6ce34..dc75c071b61 100644
--- a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/executor/DriverExecutor.java
+++ b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/executor/DriverExecutor.java
@@ -19,14 +19,13 @@ package org.apache.shardingsphere.driver.executor;
 
 import lombok.Getter;
 import org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection;
-import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.database.type.DatabaseTypeEngine;
 import org.apache.shardingsphere.infra.executor.kernel.ExecutorEngine;
 import org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutor;
 import org.apache.shardingsphere.infra.executor.sql.execute.engine.raw.RawExecutor;
+import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
-import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutor;
-import org.apache.shardingsphere.sqlfederation.rule.SQLFederationRule;
+import org.apache.shardingsphere.sqlfederation.engine.SQLFederationEngine;
 import org.apache.shardingsphere.traffic.executor.TrafficExecutor;
 
 import java.sql.SQLException;
@@ -41,7 +40,7 @@ public final class DriverExecutor implements AutoCloseable {
     
     private final RawExecutor rawExecutor;
     
-    private final SQLFederationExecutor federationExecutor;
+    private final SQLFederationEngine sqlFederationEngine;
     
     private final TrafficExecutor trafficExecutor;
     
@@ -51,11 +50,9 @@ public final class DriverExecutor implements AutoCloseable {
         JDBCExecutor jdbcExecutor = new JDBCExecutor(executorEngine, connection.getDatabaseConnectionManager().getConnectionContext());
         regularExecutor = new DriverJDBCExecutor(connection.getDatabaseName(), connection.getContextManager(), jdbcExecutor);
         rawExecutor = new RawExecutor(executorEngine, connection.getDatabaseConnectionManager().getConnectionContext());
-        DatabaseType protocolType = metaDataContexts.getMetaData().getDatabase(connection.getDatabaseName()).getProtocolType();
-        String schemaName = DatabaseTypeEngine.getDefaultSchemaName(protocolType, connection.getDatabaseName());
-        SQLFederationRule sqlFederationRule = metaDataContexts.getMetaData().getGlobalRuleMetaData().getSingleRule(SQLFederationRule.class);
-        federationExecutor = sqlFederationRule.getSqlFederationExecutor();
-        federationExecutor.init(connection.getDatabaseName(), schemaName, metaDataContexts.getMetaData(), metaDataContexts.getShardingSphereData(), jdbcExecutor);
+        ShardingSphereDatabase database = metaDataContexts.getMetaData().getDatabase(connection.getDatabaseName());
+        String schemaName = DatabaseTypeEngine.getDefaultSchemaName(database.getProtocolType(), connection.getDatabaseName());
+        sqlFederationEngine = new SQLFederationEngine(connection.getDatabaseName(), schemaName, metaDataContexts.getMetaData(), metaDataContexts.getShardingSphereData(), jdbcExecutor);
         trafficExecutor = new TrafficExecutor();
     }
     
@@ -66,7 +63,7 @@ public final class DriverExecutor implements AutoCloseable {
      */
     @Override
     public void close() throws SQLException {
-        federationExecutor.close();
+        sqlFederationEngine.close();
         trafficExecutor.close();
     }
 }
diff --git a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
index 1757fbb3ef2..4e91808158a 100644
--- a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
+++ b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSpherePreparedStatement.java
@@ -84,7 +84,6 @@ import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
 import org.apache.shardingsphere.parser.rule.SQLParserRule;
 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.sqlfederation.decider.SQLFederationDecideEngine;
 import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutorContext;
 import org.apache.shardingsphere.traffic.engine.TrafficEngine;
 import org.apache.shardingsphere.traffic.exception.metadata.EmptyTrafficExecutionUnitException;
@@ -253,7 +252,7 @@ public final class ShardingSpherePreparedStatement extends AbstractPreparedState
     }
     
     private boolean decide(final QueryContext queryContext, final ShardingSphereDatabase database, final ShardingSphereRuleMetaData globalRuleMetaData) {
-        return new SQLFederationDecideEngine(database.getRuleMetaData().getRules()).decide(queryContext.getSqlStatementContext(), queryContext.getParameters(), database, globalRuleMetaData);
+        return executor.getSqlFederationEngine().decide(queryContext.getSqlStatementContext(), queryContext.getParameters(), database, globalRuleMetaData);
     }
     
     private JDBCExecutionUnit createTrafficExecutionUnit(final String trafficInstanceId, final QueryContext queryContext) throws SQLException {
@@ -308,7 +307,7 @@ public final class ShardingSpherePreparedStatement extends AbstractPreparedState
         PreparedStatementExecuteQueryCallback callback = new PreparedStatementExecuteQueryCallback(metaDataContexts.getMetaData().getDatabase(connection.getDatabaseName()).getProtocolType(),
                 metaDataContexts.getMetaData().getDatabase(connection.getDatabaseName()).getResourceMetaData().getStorageTypes(), sqlStatement, SQLExecutorExceptionHandler.isExceptionThrown());
         SQLFederationExecutorContext context = new SQLFederationExecutorContext(false, queryContext, metaDataContexts.getMetaData());
-        return executor.getFederationExecutor().executeQuery(createDriverExecutionPrepareEngine(), callback, context);
+        return executor.getSqlFederationEngine().executeQuery(createDriverExecutionPrepareEngine(), callback, context);
     }
     
     private DriverExecutionPrepareEngine<JDBCExecutionUnit, Connection> createDriverExecutionPrepareEngine() {
@@ -500,7 +499,7 @@ public final class ShardingSpherePreparedStatement extends AbstractPreparedState
             return executor.getTrafficExecutor().getResultSet();
         }
         if (useFederation) {
-            return executor.getFederationExecutor().getResultSet();
+            return executor.getSqlFederationEngine().getResultSet();
         }
         if (executionContext.getSqlStatementContext() instanceof SelectStatementContext || executionContext.getSqlStatementContext().getSqlStatement() instanceof DALStatement) {
             List<ResultSet> resultSets = getResultSets();
diff --git a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
index e974a18edd8..9e90c986604 100644
--- a/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
+++ b/jdbc/core/src/main/java/org/apache/shardingsphere/driver/jdbc/core/statement/ShardingSphereStatement.java
@@ -79,7 +79,6 @@ import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
 import org.apache.shardingsphere.parser.rule.SQLParserRule;
 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.sqlfederation.decider.SQLFederationDecideEngine;
 import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutorContext;
 import org.apache.shardingsphere.traffic.engine.TrafficEngine;
 import org.apache.shardingsphere.traffic.exception.metadata.EmptyTrafficExecutionUnitException;
@@ -192,7 +191,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
     }
     
     private boolean decide(final QueryContext queryContext, final ShardingSphereDatabase database, final ShardingSphereRuleMetaData globalRuleMetaData) {
-        return new SQLFederationDecideEngine(database.getRuleMetaData().getRules()).decide(queryContext.getSqlStatementContext(), queryContext.getParameters(), database, globalRuleMetaData);
+        return executor.getSqlFederationEngine().decide(queryContext.getSqlStatementContext(), queryContext.getParameters(), database, globalRuleMetaData);
     }
     
     private Optional<String> getInstanceIdAndSet(final QueryContext queryContext) {
@@ -231,7 +230,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
                 metaDataContexts.getMetaData().getDatabase(connection.getDatabaseName()).getResourceMetaData().getStorageTypes(), queryContext.getSqlStatementContext().getSqlStatement(),
                 SQLExecutorExceptionHandler.isExceptionThrown());
         SQLFederationExecutorContext context = new SQLFederationExecutorContext(false, queryContext, metaDataContexts.getMetaData());
-        return executor.getFederationExecutor().executeQuery(createDriverExecutionPrepareEngine(), callback, context);
+        return executor.getSqlFederationEngine().executeQuery(createDriverExecutionPrepareEngine(), callback, context);
     }
     
     private DriverExecutionPrepareEngine<JDBCExecutionUnit, Connection> createDriverExecutionPrepareEngine() {
@@ -585,7 +584,7 @@ public final class ShardingSphereStatement extends AbstractStatementAdapter {
             return executor.getTrafficExecutor().getResultSet();
         }
         if (useFederation) {
-            return executor.getFederationExecutor().getResultSet();
+            return executor.getSqlFederationEngine().getResultSet();
         }
         if (executionContext.getSqlStatementContext() instanceof SelectStatementContext || executionContext.getSqlStatementContext().getSqlStatement() instanceof DALStatement) {
             List<ResultSet> resultSets = getResultSets();
diff --git a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/decider/SQLFederationDecideEngine.java b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/decider/SQLFederationDecideEngine.java
deleted file mode 100644
index 4f2b93206fa..00000000000
--- a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/decider/SQLFederationDecideEngine.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.sqlfederation.decider;
-
-import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
-import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
-import org.apache.shardingsphere.infra.datanode.DataNode;
-import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
-import org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
-import org.apache.shardingsphere.infra.metadata.database.schema.util.SystemSchemaUtils;
-import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
-import org.apache.shardingsphere.infra.util.spi.type.ordered.OrderedSPILoader;
-import org.apache.shardingsphere.sqlfederation.rule.SQLFederationRule;
-import org.apache.shardingsphere.sqlfederation.spi.SQLFederationDecider;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * SQL federation decide engine.
- */
-public final class SQLFederationDecideEngine {
-    
-    @SuppressWarnings("rawtypes")
-    private final Map<ShardingSphereRule, SQLFederationDecider> deciders;
-    
-    public SQLFederationDecideEngine(final Collection<ShardingSphereRule> rules) {
-        deciders = OrderedSPILoader.getServices(SQLFederationDecider.class, rules);
-    }
-    
-    /**
-     * Decide use SQL federation or not.
-     * 
-     * @param sqlStatementContext SQL statement context
-     * @param parameters SQL parameters
-     * @param database ShardingSphere database
-     * @param globalRuleMetaData global rule meta data
-     * @return use SQL federation or not
-     */
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    public boolean decide(final SQLStatementContext sqlStatementContext, final List<Object> parameters,
-                          final ShardingSphereDatabase database, final ShardingSphereRuleMetaData globalRuleMetaData) {
-        // TODO BEGIN: move this logic to SQLFederationDecider implement class when we remove sql federation type
-        if (isQuerySystemSchema(sqlStatementContext, database)) {
-            return true;
-        }
-        // TODO END
-        boolean sqlFederationEnabled = globalRuleMetaData.getSingleRule(SQLFederationRule.class).getConfiguration().isSqlFederationEnabled();
-        if (!sqlFederationEnabled || !(sqlStatementContext instanceof SelectStatementContext)) {
-            return false;
-        }
-        Collection<DataNode> includedDataNodes = new HashSet<>();
-        for (Entry<ShardingSphereRule, SQLFederationDecider> entry : deciders.entrySet()) {
-            boolean isUseSQLFederation = entry.getValue().decide((SelectStatementContext) sqlStatementContext, parameters, globalRuleMetaData, database, entry.getKey(), includedDataNodes);
-            if (isUseSQLFederation) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    private boolean isQuerySystemSchema(final SQLStatementContext sqlStatementContext, final ShardingSphereDatabase database) {
-        return sqlStatementContext instanceof SelectStatementContext
-                && SystemSchemaUtils.containsSystemSchema(sqlStatementContext.getDatabaseType(), sqlStatementContext.getTablesContext().getSchemaNames(), database);
-    }
-}
diff --git a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/executor/SQLFederationExecutor.java b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngine.java
similarity index 52%
rename from kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/executor/SQLFederationExecutor.java
rename to kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngine.java
index 30f32a2aa0f..8461bd797ff 100644
--- a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/executor/SQLFederationExecutor.java
+++ b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngine.java
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sqlfederation.executor;
+package org.apache.shardingsphere.sqlfederation.engine;
 
-import com.google.common.base.Preconditions;
+import lombok.Getter;
 import org.apache.calcite.adapter.enumerable.EnumerableInterpretable;
 import org.apache.calcite.adapter.enumerable.EnumerableRel;
 import org.apache.calcite.linq4j.Enumerator;
@@ -28,7 +28,7 @@ import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql2rel.SqlToRelConverter;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
-import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import org.apache.shardingsphere.infra.datanode.DataNode;
 import org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutionUnit;
 import org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutor;
 import org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutorCallback;
@@ -39,58 +39,103 @@ import org.apache.shardingsphere.infra.metadata.data.ShardingSphereData;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
+import org.apache.shardingsphere.infra.metadata.database.schema.util.SystemSchemaUtils;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
+import org.apache.shardingsphere.infra.util.spi.type.ordered.OrderedSPILoader;
+import org.apache.shardingsphere.sqlfederation.executor.SQLFederationDataContext;
+import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutorContext;
+import org.apache.shardingsphere.sqlfederation.executor.TableScanExecutorContext;
+import org.apache.shardingsphere.sqlfederation.executor.TranslatableTableScanExecutor;
 import org.apache.shardingsphere.sqlfederation.executor.resultset.SQLFederationResultSet;
 import org.apache.shardingsphere.sqlfederation.optimizer.SQLFederationCompiler;
+import org.apache.shardingsphere.sqlfederation.optimizer.SQLFederationCompilerEngine;
 import org.apache.shardingsphere.sqlfederation.optimizer.SQLFederationExecutionPlan;
 import org.apache.shardingsphere.sqlfederation.optimizer.context.OptimizerContext;
 import org.apache.shardingsphere.sqlfederation.optimizer.context.planner.OptimizerPlannerContext;
 import org.apache.shardingsphere.sqlfederation.optimizer.executor.TableScanExecutor;
 import org.apache.shardingsphere.sqlfederation.optimizer.metadata.schema.SQLFederationTable;
 import org.apache.shardingsphere.sqlfederation.rule.SQLFederationRule;
+import org.apache.shardingsphere.sqlfederation.spi.SQLFederationDecider;
 
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.SQLException;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 
 /**
- * SQL federation executor.
+ * SQL federation engine.
  */
-public final class SQLFederationExecutor implements AutoCloseable {
+@Getter
+public final class SQLFederationEngine implements AutoCloseable {
     
-    private String databaseName;
+    @SuppressWarnings("rawtypes")
+    private final Map<ShardingSphereRule, SQLFederationDecider> deciders;
     
-    private String schemaName;
+    private final String databaseName;
     
-    private ShardingSphereRuleMetaData globalRuleMetaData;
+    private final String schemaName;
     
-    private ConfigurationProperties props;
+    private final ShardingSphereMetaData metaData;
     
-    private ShardingSphereData data;
+    private final ShardingSphereData statistics;
     
-    private JDBCExecutor jdbcExecutor;
+    private final JDBCExecutor jdbcExecutor;
+    
+    private final SQLFederationRule sqlFederationRule;
     
     private ResultSet resultSet;
     
-    /**
-     * Init SQL federation executor.
-     *
-     * @param databaseName database name
-     * @param schemaName schema name
-     * @param metaData ShardingSphere meta data
-     * @param data ShardingSphere data
-     * @param jdbcExecutor jdbc executor
-     */
-    public void init(final String databaseName, final String schemaName, final ShardingSphereMetaData metaData, final ShardingSphereData data, final JDBCExecutor jdbcExecutor) {
+    public SQLFederationEngine(final String databaseName, final String schemaName, final ShardingSphereMetaData metaData, final ShardingSphereData statistics, final JDBCExecutor jdbcExecutor) {
+        deciders = OrderedSPILoader.getServices(SQLFederationDecider.class, metaData.getDatabase(databaseName).getRuleMetaData().getRules());
         this.databaseName = databaseName;
         this.schemaName = schemaName;
-        this.globalRuleMetaData = metaData.getGlobalRuleMetaData();
-        this.props = metaData.getProps();
-        this.data = data;
+        this.metaData = metaData;
+        this.statistics = statistics;
         this.jdbcExecutor = jdbcExecutor;
+        sqlFederationRule = metaData.getGlobalRuleMetaData().getSingleRule(SQLFederationRule.class);
+    }
+    
+    /**
+     * Decide use SQL federation or not.
+     *
+     * @param sqlStatementContext SQL statement context
+     * @param parameters SQL parameters
+     * @param database ShardingSphere database
+     * @param globalRuleMetaData global rule meta data
+     * @return use SQL federation or not
+     */
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public boolean decide(final SQLStatementContext sqlStatementContext, final List<Object> parameters,
+                          final ShardingSphereDatabase database, final ShardingSphereRuleMetaData globalRuleMetaData) {
+        // TODO BEGIN: move this logic to SQLFederationDecider implement class when we remove sql federation type
+        if (isQuerySystemSchema(sqlStatementContext, database)) {
+            return true;
+        }
+        // TODO END
+        boolean sqlFederationEnabled = globalRuleMetaData.getSingleRule(SQLFederationRule.class).getConfiguration().isSqlFederationEnabled();
+        if (!sqlFederationEnabled || !(sqlStatementContext instanceof SelectStatementContext)) {
+            return false;
+        }
+        Collection<DataNode> includedDataNodes = new HashSet<>();
+        for (Entry<ShardingSphereRule, SQLFederationDecider> entry : deciders.entrySet()) {
+            boolean isUseSQLFederation = entry.getValue().decide((SelectStatementContext) sqlStatementContext, parameters, globalRuleMetaData, database, entry.getKey(), includedDataNodes);
+            if (isUseSQLFederation) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    private boolean isQuerySystemSchema(final SQLStatementContext sqlStatementContext, final ShardingSphereDatabase database) {
+        return sqlStatementContext instanceof SelectStatementContext
+                && SystemSchemaUtils.containsSystemSchema(sqlStatementContext.getDatabaseType(), sqlStatementContext.getTablesContext().getSchemaNames(), database);
     }
     
     /**
@@ -101,34 +146,34 @@ public final class SQLFederationExecutor implements AutoCloseable {
      * @param federationContext federation context
      * @return result set
      */
+    @SuppressWarnings("unchecked")
     public ResultSet executeQuery(final DriverExecutionPrepareEngine<JDBCExecutionUnit, Connection> prepareEngine,
                                   final JDBCExecutorCallback<? extends ExecuteResult> callback, final SQLFederationExecutorContext federationContext) {
         SQLStatementContext sqlStatementContext = federationContext.getQueryContext().getSqlStatementContext();
-        Preconditions.checkArgument(sqlStatementContext instanceof SelectStatementContext, "SQL statement context must be select statement context.");
-        ShardingSphereDatabase database = federationContext.getMetaData().getDatabase(databaseName);
-        ShardingSphereSchema schema = database.getSchema(schemaName);
-        OptimizerContext optimizerContext = globalRuleMetaData.getSingleRule(SQLFederationRule.class).getOptimizerContext();
-        Schema sqlFederationSchema = optimizerContext.getPlannerContext(databaseName).getValidators().get(schemaName).getCatalogReader().getRootSchema().plus().getSubSchema(schemaName);
-        registerTableScanExecutor(sqlFederationSchema, prepareEngine, callback, federationContext, optimizerContext);
+        ShardingSpherePreconditions.checkState(sqlStatementContext instanceof SelectStatementContext, () -> new IllegalArgumentException("SQL statement context must be select statement context."));
+        SelectStatementContext selectStatementContext = (SelectStatementContext) sqlStatementContext;
+        Schema sqlFederationSchema =
+                sqlFederationRule.getOptimizerContext().getPlannerContext(databaseName).getValidators().get(schemaName).getCatalogReader().getRootSchema().plus().getSubSchema(schemaName);
+        registerTableScanExecutor(sqlFederationSchema, prepareEngine, callback, federationContext, sqlFederationRule.getOptimizerContext());
+        OptimizerPlannerContext plannerContext = sqlFederationRule.getOptimizerContext().getPlannerContext(databaseName);
+        SqlValidator sqlValidator = plannerContext.getValidators().get(schemaName);
+        SqlToRelConverter sqlToRelConverter = plannerContext.getConverters().get(schemaName);
+        SQLFederationCompilerEngine compilerEngine =
+                new SQLFederationCompilerEngine(new SQLFederationCompiler(sqlToRelConverter, plannerContext.getHepPlanner()), sqlFederationRule.getConfiguration().getExecutionPlanCache());
+        SQLFederationExecutionPlan executionPlan = compilerEngine.compile(selectStatementContext.getSqlStatement(), false);
+        Bindable<Object> executablePlan = EnumerableInterpretable.toBindable(Collections.emptyMap(), null, (EnumerableRel) executionPlan.getPhysicalPlan(), EnumerableRel.Prefer.ARRAY);
         Map<String, Object> params = createParameters(federationContext.getQueryContext().getParameters());
-        resultSet = execute((SelectStatementContext) sqlStatementContext, schema, sqlFederationSchema, params, optimizerContext);
+        Enumerator<Object> enumerator = executablePlan.bind(new SQLFederationDataContext(sqlValidator, sqlToRelConverter, params)).enumerator();
+        ShardingSphereSchema schema = federationContext.getMetaData().getDatabase(databaseName).getSchema(schemaName);
+        resultSet = new SQLFederationResultSet(enumerator, schema, sqlFederationSchema, selectStatementContext, executionPlan.getResultColumnType());
         return resultSet;
     }
     
-    private Map<String, Object> createParameters(final List<Object> params) {
-        Map<String, Object> result = new HashMap<>(params.size(), 1F);
-        int index = 0;
-        for (Object each : params) {
-            result.put("?" + index++, each);
-        }
-        return result;
-    }
-    
     private void registerTableScanExecutor(final Schema sqlFederationSchema, final DriverExecutionPrepareEngine<JDBCExecutionUnit, Connection> prepareEngine,
                                            final JDBCExecutorCallback<? extends ExecuteResult> callback, final SQLFederationExecutorContext federationContext,
                                            final OptimizerContext optimizerContext) {
-        TableScanExecutorContext executorContext = new TableScanExecutorContext(databaseName, schemaName, props, federationContext);
-        TableScanExecutor executor = new TranslatableTableScanExecutor(prepareEngine, jdbcExecutor, callback, optimizerContext, globalRuleMetaData, executorContext, data);
+        TableScanExecutorContext executorContext = new TableScanExecutorContext(databaseName, schemaName, metaData.getProps(), federationContext);
+        TableScanExecutor executor = new TranslatableTableScanExecutor(prepareEngine, jdbcExecutor, callback, optimizerContext, metaData.getGlobalRuleMetaData(), executorContext, statistics);
         for (String each : federationContext.getQueryContext().getSqlStatementContext().getTablesContext().getTableNames()) {
             Table table = sqlFederationSchema.getTable(each);
             if (table instanceof SQLFederationTable) {
@@ -137,32 +182,16 @@ public final class SQLFederationExecutor implements AutoCloseable {
         }
     }
     
-    @SuppressWarnings("unchecked")
-    private ResultSet execute(final SelectStatementContext selectStatementContext, final ShardingSphereSchema schema, final Schema sqlFederationSchema, final Map<String, Object> params,
-                              final OptimizerContext optimizerContext) {
-        OptimizerPlannerContext plannerContext = optimizerContext.getPlannerContext(databaseName);
-        SqlValidator sqlValidator = plannerContext.getValidators().get(schemaName);
-        SqlToRelConverter sqlToRelConverter = plannerContext.getConverters().get(schemaName);
-        SQLFederationExecutionPlan executionPlan = new SQLFederationCompiler(sqlToRelConverter, plannerContext.getHepPlanner()).compile(selectStatementContext.getSqlStatement());
-        Bindable<Object> executablePlan = EnumerableInterpretable.toBindable(Collections.emptyMap(), null, (EnumerableRel) executionPlan.getPhysicalPlan(), EnumerableRel.Prefer.ARRAY);
-        Enumerator<Object> enumerator = executablePlan.bind(new SQLFederationDataContext(sqlValidator, sqlToRelConverter, params)).enumerator();
-        return new SQLFederationResultSet(enumerator, schema, sqlFederationSchema, selectStatementContext, executionPlan.getResultColumnType());
-    }
-    
-    /**
-     * Get result set.
-     *
-     * @return result set
-     */
-    public ResultSet getResultSet() {
-        return resultSet;
+    private Map<String, Object> createParameters(final List<Object> params) {
+        Map<String, Object> result = new HashMap<>(params.size(), 1F);
+        int index = 0;
+        for (Object each : params) {
+            result.put("?" + index++, each);
+        }
+        return result;
     }
     
-    /**
-     * Close.
-     * 
-     * @throws SQLException sql exception
-     */
+    @Override
     public void close() throws SQLException {
         if (null != resultSet) {
             resultSet.close();
diff --git a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/SQLFederationCompilerEngine.java b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/SQLFederationCompilerEngine.java
new file mode 100644
index 00000000000..b878fbebbdb
--- /dev/null
+++ b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/SQLFederationCompilerEngine.java
@@ -0,0 +1,49 @@
+/*
+ * 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.sqlfederation.optimizer;
+
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import org.apache.shardingsphere.sql.parser.api.CacheOption;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.apache.shardingsphere.sqlfederation.optimizer.planner.cache.ExecutionPlanCacheBuilder;
+
+/**
+ * SQL federation compiler engine.
+ */
+public final class SQLFederationCompilerEngine {
+    
+    private final SQLFederationCompiler sqlFederationCompiler;
+    
+    private final LoadingCache<SQLStatement, SQLFederationExecutionPlan> executionPlanCache;
+    
+    public SQLFederationCompilerEngine(final SQLFederationCompiler sqlFederationCompiler, final CacheOption cacheOption) {
+        this.sqlFederationCompiler = sqlFederationCompiler;
+        executionPlanCache = ExecutionPlanCacheBuilder.build(cacheOption, sqlFederationCompiler);
+    }
+    
+    /**
+     * Compile sql statement to execution plan.
+     *
+     * @param sqlStatement SQL statement
+     * @param useCache use cache
+     * @return sql federation execution plan
+     */
+    public SQLFederationExecutionPlan compile(final SQLStatement sqlStatement, final boolean useCache) {
+        return useCache ? executionPlanCache.get(sqlStatement) : sqlFederationCompiler.compile(sqlStatement);
+    }
+}
diff --git a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/planner/cache/ExecutionPlanCacheBuilder.java b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/planner/cache/ExecutionPlanCacheBuilder.java
new file mode 100644
index 00000000000..8bbef83cf16
--- /dev/null
+++ b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/planner/cache/ExecutionPlanCacheBuilder.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.sqlfederation.optimizer.planner.cache;
+
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.sql.parser.api.CacheOption;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.apache.shardingsphere.sqlfederation.optimizer.SQLFederationCompiler;
+import org.apache.shardingsphere.sqlfederation.optimizer.SQLFederationExecutionPlan;
+
+/**
+ * Execution plan cache builder.
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public final class ExecutionPlanCacheBuilder {
+    
+    /**
+     * Build execution plan cache.
+     *
+     * @param executionPlanCache execution plan cache option
+     * @param sqlFederationCompiler sql federation compiler
+     * @return built execution plan cache
+     */
+    public static LoadingCache<SQLStatement, SQLFederationExecutionPlan> build(final CacheOption executionPlanCache, final SQLFederationCompiler sqlFederationCompiler) {
+        return Caffeine.newBuilder().softValues().initialCapacity(executionPlanCache.getInitialCapacity()).maximumSize(executionPlanCache.getMaximumSize())
+                .build(new ExecutionPlanCacheLoader(sqlFederationCompiler));
+    }
+}
diff --git a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/planner/cache/ExecutionPlanCacheLoader.java b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/planner/cache/ExecutionPlanCacheLoader.java
new file mode 100644
index 00000000000..0a88d744c04
--- /dev/null
+++ b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/optimizer/planner/cache/ExecutionPlanCacheLoader.java
@@ -0,0 +1,43 @@
+/*
+ * 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.sqlfederation.optimizer.planner.cache;
+
+import com.github.benmanes.caffeine.cache.CacheLoader;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.apache.shardingsphere.sqlfederation.optimizer.SQLFederationCompiler;
+import org.apache.shardingsphere.sqlfederation.optimizer.SQLFederationExecutionPlan;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+
+/**
+ * Execution plan cache loader.
+ */
+public final class ExecutionPlanCacheLoader implements CacheLoader<SQLStatement, SQLFederationExecutionPlan> {
+    
+    private final SQLFederationCompiler sqlFederationCompiler;
+    
+    public ExecutionPlanCacheLoader(final SQLFederationCompiler sqlFederationCompiler) {
+        this.sqlFederationCompiler = sqlFederationCompiler;
+    }
+    
+    @ParametersAreNonnullByDefault
+    @Override
+    public SQLFederationExecutionPlan load(final SQLStatement sqlStatement) {
+        return sqlFederationCompiler.compile(sqlStatement);
+    }
+}
diff --git a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/rule/SQLFederationRule.java b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/rule/SQLFederationRule.java
index e61c695d6b0..78b84f8a168 100644
--- a/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/rule/SQLFederationRule.java
+++ b/kernel/sql-federation/core/src/main/java/org/apache/shardingsphere/sqlfederation/rule/SQLFederationRule.java
@@ -23,7 +23,6 @@ import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.rule.identifier.scope.GlobalRule;
 import org.apache.shardingsphere.infra.rule.identifier.type.MetaDataHeldRule;
 import org.apache.shardingsphere.sqlfederation.api.config.SQLFederationRuleConfiguration;
-import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutor;
 import org.apache.shardingsphere.sqlfederation.optimizer.context.OptimizerContext;
 import org.apache.shardingsphere.sqlfederation.optimizer.context.OptimizerContextFactory;
 import org.apache.shardingsphere.sqlfederation.optimizer.context.planner.OptimizerPlannerContext;
@@ -39,13 +38,10 @@ public final class SQLFederationRule implements GlobalRule, MetaDataHeldRule {
     
     private final SQLFederationRuleConfiguration configuration;
     
-    private final SQLFederationExecutor sqlFederationExecutor;
-    
     private final OptimizerContext optimizerContext;
     
     public SQLFederationRule(final SQLFederationRuleConfiguration ruleConfig, final Map<String, ShardingSphereDatabase> databases, final ConfigurationProperties props) {
         configuration = ruleConfig;
-        sqlFederationExecutor = new SQLFederationExecutor();
         optimizerContext = OptimizerContextFactory.create(databases, props);
     }
     
diff --git a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/engine/SQLFederationDecideEngineTest.java b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngineTest.java
similarity index 52%
rename from kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/engine/SQLFederationDecideEngineTest.java
rename to kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngineTest.java
index e19c4c31037..40f45bfaa65 100644
--- a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/engine/SQLFederationDecideEngineTest.java
+++ b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/SQLFederationEngineTest.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sqlfederation.decider.engine;
+package org.apache.shardingsphere.sqlfederation.engine;
 
 import org.apache.shardingsphere.infra.binder.statement.CommonSQLStatementContext;
 import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
@@ -23,18 +23,25 @@ import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
 import org.apache.shardingsphere.infra.database.DefaultDatabase;
 import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType;
+import org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutor;
+import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
+import org.apache.shardingsphere.infra.metadata.data.ShardingSphereData;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.resource.ShardingSphereResourceMetaData;
 import org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.sql.parser.api.CacheOption;
 import org.apache.shardingsphere.sqlfederation.api.config.SQLFederationRuleConfiguration;
-import org.apache.shardingsphere.sqlfederation.decider.SQLFederationDecideEngine;
-import org.apache.shardingsphere.sqlfederation.decider.fixture.rule.SQLFederationDeciderRuleMatchFixture;
-import org.apache.shardingsphere.sqlfederation.decider.fixture.rule.SQLFederationDeciderRuleNotMatchFixture;
+import org.apache.shardingsphere.sqlfederation.engine.fixture.rule.SQLFederationDeciderRuleMatchFixture;
+import org.apache.shardingsphere.sqlfederation.engine.fixture.rule.SQLFederationDeciderRuleNotMatchFixture;
 import org.apache.shardingsphere.sqlfederation.rule.SQLFederationRule;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
 
+import java.sql.SQLException;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -45,75 +52,91 @@ import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
-class SQLFederationDecideEngineTest {
+@ExtendWith(MockitoExtension.class)
+class SQLFederationEngineTest {
+    
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+    private ShardingSphereMetaData metaData;
     
     @Test
-    void assertDecideWhenSelectStatementContainsSystemSchema() {
-        SQLFederationDecideEngine engine = new SQLFederationDecideEngine(Collections.emptyList());
+    void assertDecideWhenSelectStatementContainsSystemSchema() throws SQLException {
+        Collection<ShardingSphereRule> globalRules =
+                Collections.singletonList(new SQLFederationRule(new SQLFederationRuleConfiguration(false, mock(CacheOption.class)), Collections.emptyMap(), mock(ConfigurationProperties.class)));
+        SQLFederationEngine engine = createSQLFederationEngine(globalRules, Collections.emptyList());
         SelectStatementContext sqlStatementContext = mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
         when(sqlStatementContext.getDatabaseType()).thenReturn(new MySQLDatabaseType());
         when(sqlStatementContext.getTablesContext().getSchemaNames()).thenReturn(Collections.singletonList("information_schema"));
         ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
                 mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), mock(ShardingSphereRuleMetaData.class), Collections.emptyMap());
         assertTrue(engine.decide(sqlStatementContext, Collections.emptyList(), database, mock(ShardingSphereRuleMetaData.class)));
+        engine.close();
+    }
+    
+    private SQLFederationEngine createSQLFederationEngine(final Collection<ShardingSphereRule> globalRules, final Collection<ShardingSphereRule> databaseRules) {
+        when(metaData.getDatabase(DefaultDatabase.LOGIC_NAME).getRuleMetaData().getRules()).thenReturn(databaseRules);
+        when(metaData.getGlobalRuleMetaData()).thenReturn(new ShardingSphereRuleMetaData(globalRules));
+        return new SQLFederationEngine(DefaultDatabase.LOGIC_NAME, DefaultDatabase.LOGIC_NAME, metaData, mock(ShardingSphereData.class), mock(JDBCExecutor.class));
     }
     
     @Test
-    void assertDecideWhenNotConfigSqlFederationEnabled() {
-        Collection<ShardingSphereRule> rules =
+    void assertDecideWhenNotConfigSqlFederationEnabled() throws SQLException {
+        Collection<ShardingSphereRule> globalRules =
                 Collections.singletonList(new SQLFederationRule(new SQLFederationRuleConfiguration(false, mock(CacheOption.class)), Collections.emptyMap(), mock(ConfigurationProperties.class)));
-        SQLFederationDecideEngine engine = new SQLFederationDecideEngine(rules);
+        SQLFederationEngine engine = createSQLFederationEngine(globalRules, Collections.emptyList());
         ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
-                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules), Collections.emptyMap());
-        ShardingSphereRuleMetaData globalRuleMetaData = new ShardingSphereRuleMetaData(rules);
+                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(globalRules), Collections.emptyMap());
+        ShardingSphereRuleMetaData globalRuleMetaData = new ShardingSphereRuleMetaData(globalRules);
         assertFalse(engine.decide(mock(CommonSQLStatementContext.class), Collections.emptyList(), database, globalRuleMetaData));
+        engine.close();
     }
     
     @Test
-    void assertDecideWhenExecuteNotSelectStatement() {
-        Collection<ShardingSphereRule> rules =
+    void assertDecideWhenExecuteNotSelectStatement() throws SQLException {
+        Collection<ShardingSphereRule> globalRules =
                 Collections.singletonList(new SQLFederationRule(new SQLFederationRuleConfiguration(true, mock(CacheOption.class)), Collections.emptyMap(), mock(ConfigurationProperties.class)));
-        SQLFederationDecideEngine engine = new SQLFederationDecideEngine(rules);
+        SQLFederationEngine engine = createSQLFederationEngine(globalRules, Collections.emptyList());
         ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
-                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules), Collections.emptyMap());
-        ShardingSphereRuleMetaData globalRuleMetaData = new ShardingSphereRuleMetaData(rules);
+                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(globalRules), Collections.emptyMap());
+        ShardingSphereRuleMetaData globalRuleMetaData = new ShardingSphereRuleMetaData(globalRules);
         assertFalse(engine.decide(mock(CommonSQLStatementContext.class), Collections.emptyList(), database, globalRuleMetaData));
+        engine.close();
     }
     
     @Test
-    void assertDecideWhenConfigSingleMatchedRule() {
-        Collection<ShardingSphereRule> rules =
-                Arrays.asList(new SQLFederationRule(new SQLFederationRuleConfiguration(true, mock(CacheOption.class)), Collections.emptyMap(), mock(ConfigurationProperties.class)),
-                        new SQLFederationDeciderRuleMatchFixture());
-        SQLFederationDecideEngine engine = new SQLFederationDecideEngine(rules);
+    void assertDecideWhenConfigSingleMatchedRule() throws SQLException {
+        Collection<ShardingSphereRule> globalRules =
+                Collections.singletonList(new SQLFederationRule(new SQLFederationRuleConfiguration(true, mock(CacheOption.class)), Collections.emptyMap(), mock(ConfigurationProperties.class)));
+        Collection<ShardingSphereRule> databaseRules = Collections.singletonList(new SQLFederationDeciderRuleMatchFixture());
+        SQLFederationEngine engine = createSQLFederationEngine(globalRules, databaseRules);
         ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
-                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules), Collections.emptyMap());
-        ShardingSphereRuleMetaData globalRuleMetaData = new ShardingSphereRuleMetaData(rules);
+                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(globalRules), Collections.emptyMap());
+        ShardingSphereRuleMetaData globalRuleMetaData = new ShardingSphereRuleMetaData(globalRules);
         assertTrue(engine.decide(mock(SelectStatementContext.class, RETURNS_DEEP_STUBS), Collections.emptyList(), database, globalRuleMetaData));
+        engine.close();
     }
     
     @Test
-    void assertDecideWhenConfigSingleNotMatchedRule() {
-        Collection<ShardingSphereRule> rules =
-                Arrays.asList(new SQLFederationRule(new SQLFederationRuleConfiguration(true, mock(CacheOption.class)), Collections.emptyMap(), mock(ConfigurationProperties.class)),
-                        new SQLFederationDeciderRuleNotMatchFixture());
-        SQLFederationDecideEngine engine = new SQLFederationDecideEngine(rules);
+    void assertDecideWhenConfigSingleNotMatchedRule() throws SQLException {
+        Collection<ShardingSphereRule> globalRules =
+                Collections.singletonList(new SQLFederationRule(new SQLFederationRuleConfiguration(true, mock(CacheOption.class)), Collections.emptyMap(), mock(ConfigurationProperties.class)));
+        Collection<ShardingSphereRule> databaseRules = Collections.singletonList(new SQLFederationDeciderRuleNotMatchFixture());
+        SQLFederationEngine engine = createSQLFederationEngine(globalRules, databaseRules);
         ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
-                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules), Collections.emptyMap());
-        ShardingSphereRuleMetaData globalRuleMetaData = new ShardingSphereRuleMetaData(rules);
-        assertFalse(engine.decide(mock(SelectStatementContext.class, RETURNS_DEEP_STUBS), Collections.emptyList(), database, globalRuleMetaData));
+                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(databaseRules), Collections.emptyMap());
+        assertFalse(engine.decide(mock(SelectStatementContext.class, RETURNS_DEEP_STUBS), Collections.emptyList(), database, new ShardingSphereRuleMetaData(globalRules)));
+        engine.close();
     }
     
     @Test
-    void assertDecideWhenConfigMultiRule() {
-        Collection<ShardingSphereRule> rules =
-                Arrays.asList(new SQLFederationRule(new SQLFederationRuleConfiguration(true, mock(CacheOption.class)), Collections.emptyMap(), mock(ConfigurationProperties.class)),
-                        new SQLFederationDeciderRuleNotMatchFixture(),
-                        new SQLFederationDeciderRuleMatchFixture());
-        SQLFederationDecideEngine engine = new SQLFederationDecideEngine(rules);
+    void assertDecideWhenConfigMultiRule() throws SQLException {
+        Collection<ShardingSphereRule> globalRules =
+                Collections.singletonList(new SQLFederationRule(new SQLFederationRuleConfiguration(true, mock(CacheOption.class)), Collections.emptyMap(), mock(ConfigurationProperties.class)));
+        Collection<ShardingSphereRule> databaseRules = Arrays.asList(new SQLFederationDeciderRuleNotMatchFixture(),
+                new SQLFederationDeciderRuleMatchFixture());
+        SQLFederationEngine engine = createSQLFederationEngine(globalRules, databaseRules);
         ShardingSphereDatabase database = new ShardingSphereDatabase(DefaultDatabase.LOGIC_NAME,
-                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(rules), Collections.emptyMap());
-        ShardingSphereRuleMetaData globalRuleMetaData = new ShardingSphereRuleMetaData(rules);
-        assertTrue(engine.decide(mock(SelectStatementContext.class, RETURNS_DEEP_STUBS), Collections.emptyList(), database, globalRuleMetaData));
+                mock(DatabaseType.class), mock(ShardingSphereResourceMetaData.class, RETURNS_DEEP_STUBS), new ShardingSphereRuleMetaData(databaseRules), Collections.emptyMap());
+        assertTrue(engine.decide(mock(SelectStatementContext.class, RETURNS_DEEP_STUBS), Collections.emptyList(), database, new ShardingSphereRuleMetaData(globalRules)));
+        engine.close();
     }
 }
diff --git a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/decider/SQLFederationDeciderMatchFixture.java b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/decider/SQLFederationDeciderMatchFixture.java
similarity index 91%
rename from kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/decider/SQLFederationDeciderMatchFixture.java
rename to kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/decider/SQLFederationDeciderMatchFixture.java
index 83ea8483fab..93dc7bc24d2 100644
--- a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/decider/SQLFederationDeciderMatchFixture.java
+++ b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/decider/SQLFederationDeciderMatchFixture.java
@@ -15,13 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sqlfederation.decider.fixture.decider;
+package org.apache.shardingsphere.sqlfederation.engine.fixture.decider;
 
 import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.datanode.DataNode;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
-import org.apache.shardingsphere.sqlfederation.decider.fixture.rule.SQLFederationDeciderRuleMatchFixture;
+import org.apache.shardingsphere.sqlfederation.engine.fixture.rule.SQLFederationDeciderRuleMatchFixture;
 import org.apache.shardingsphere.sqlfederation.spi.SQLFederationDecider;
 
 import java.util.Collection;
diff --git a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/decider/SQLFederationDeciderNotMatchFixture.java b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/decider/SQLFederationDeciderNotMatchFixture.java
similarity index 91%
rename from kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/decider/SQLFederationDeciderNotMatchFixture.java
rename to kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/decider/SQLFederationDeciderNotMatchFixture.java
index 144ad281fbf..9f1df1d075d 100644
--- a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/decider/SQLFederationDeciderNotMatchFixture.java
+++ b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/decider/SQLFederationDeciderNotMatchFixture.java
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sqlfederation.decider.fixture.decider;
+package org.apache.shardingsphere.sqlfederation.engine.fixture.decider;
 
-import org.apache.shardingsphere.sqlfederation.decider.fixture.rule.SQLFederationDeciderRuleNotMatchFixture;
+import org.apache.shardingsphere.sqlfederation.engine.fixture.rule.SQLFederationDeciderRuleNotMatchFixture;
 import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.datanode.DataNode;
 import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
diff --git a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/rule/SQLFederationDeciderRuleMatchFixture.java b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/rule/SQLFederationDeciderRuleMatchFixture.java
similarity index 95%
rename from kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/rule/SQLFederationDeciderRuleMatchFixture.java
rename to kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/rule/SQLFederationDeciderRuleMatchFixture.java
index 140182978ef..25dad8dbcd9 100644
--- a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/rule/SQLFederationDeciderRuleMatchFixture.java
+++ b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/rule/SQLFederationDeciderRuleMatchFixture.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sqlfederation.decider.fixture.rule;
+package org.apache.shardingsphere.sqlfederation.engine.fixture.rule;
 
 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
diff --git a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/rule/SQLFederationDeciderRuleNotMatchFixture.java b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/rule/SQLFederationDeciderRuleNotMatchFixture.java
similarity index 95%
rename from kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/rule/SQLFederationDeciderRuleNotMatchFixture.java
rename to kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/rule/SQLFederationDeciderRuleNotMatchFixture.java
index e20ae778db8..36788a0f27b 100644
--- a/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/decider/fixture/rule/SQLFederationDeciderRuleNotMatchFixture.java
+++ b/kernel/sql-federation/core/src/test/java/org/apache/shardingsphere/sqlfederation/engine/fixture/rule/SQLFederationDeciderRuleNotMatchFixture.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.sqlfederation.decider.fixture.rule;
+package org.apache.shardingsphere.sqlfederation.engine.fixture.rule;
 
 import org.apache.shardingsphere.infra.config.rule.RuleConfiguration;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
diff --git a/kernel/sql-federation/core/src/test/resources/META-INF/services/org.apache.shardingsphere.sqlfederation.spi.SQLFederationDecider b/kernel/sql-federation/core/src/test/resources/META-INF/services/org.apache.shardingsphere.sqlfederation.spi.SQLFederationDecider
index ee4e53ac1e9..c347588950b 100644
--- a/kernel/sql-federation/core/src/test/resources/META-INF/services/org.apache.shardingsphere.sqlfederation.spi.SQLFederationDecider
+++ b/kernel/sql-federation/core/src/test/resources/META-INF/services/org.apache.shardingsphere.sqlfederation.spi.SQLFederationDecider
@@ -15,5 +15,5 @@
 # limitations under the License.
 #
 
-org.apache.shardingsphere.sqlfederation.decider.fixture.decider.SQLFederationDeciderMatchFixture
-org.apache.shardingsphere.sqlfederation.decider.fixture.decider.SQLFederationDeciderNotMatchFixture
+org.apache.shardingsphere.sqlfederation.engine.fixture.decider.SQLFederationDeciderMatchFixture
+org.apache.shardingsphere.sqlfederation.engine.fixture.decider.SQLFederationDeciderNotMatchFixture
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
index 3fcaeb143b2..ee3a12740f5 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnector.java
@@ -31,11 +31,9 @@ import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
 import org.apache.shardingsphere.infra.connection.kernel.KernelProcessor;
 import org.apache.shardingsphere.infra.connection.refresher.MetaDataRefreshEngine;
 import org.apache.shardingsphere.infra.database.type.DatabaseType;
-import org.apache.shardingsphere.infra.database.type.DatabaseTypeEngine;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
 import org.apache.shardingsphere.infra.executor.sql.execute.engine.SQLExecutorExceptionHandler;
 import org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutionUnit;
-import org.apache.shardingsphere.infra.executor.sql.execute.engine.driver.jdbc.JDBCExecutor;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.impl.driver.jdbc.metadata.JDBCQueryResultMetaData;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.impl.driver.jdbc.type.stream.JDBCStreamQueryResult;
@@ -55,7 +53,6 @@ import org.apache.shardingsphere.proxy.backend.connector.jdbc.executor.callback.
 import org.apache.shardingsphere.proxy.backend.connector.jdbc.executor.callback.ProxyJDBCExecutorCallbackFactory;
 import org.apache.shardingsphere.proxy.backend.connector.jdbc.statement.JDBCBackendStatement;
 import org.apache.shardingsphere.proxy.backend.connector.jdbc.transaction.BackendTransactionManager;
-import org.apache.shardingsphere.proxy.backend.context.BackendExecutorContext;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.exception.RuleNotExistedException;
 import org.apache.shardingsphere.proxy.backend.exception.StorageUnitNotExistedException;
@@ -74,10 +71,7 @@ import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.DMLStatement;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.dml.SelectStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLInsertStatement;
-import org.apache.shardingsphere.sqlfederation.decider.SQLFederationDecideEngine;
-import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutor;
 import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutorContext;
-import org.apache.shardingsphere.sqlfederation.rule.SQLFederationRule;
 import org.apache.shardingsphere.transaction.api.TransactionType;
 
 import java.sql.Connection;
@@ -114,8 +108,6 @@ public final class DatabaseConnector implements DatabaseBackendHandler {
     
     private final ProxyDatabaseConnectionManager databaseConnectionManager;
     
-    private SQLFederationExecutor federationExecutor;
-    
     private List<QueryHeader> queryHeaders;
     
     private MergedResult mergedResult;
@@ -131,7 +123,7 @@ public final class DatabaseConnector implements DatabaseBackendHandler {
         if (sqlStatementContext instanceof CursorAvailable) {
             prepareCursorStatementContext((CursorAvailable) sqlStatementContext, databaseConnectionManager.getConnectionSession());
         }
-        proxySQLExecutor = new ProxySQLExecutor(driverType, databaseConnectionManager, this);
+        proxySQLExecutor = new ProxySQLExecutor(driverType, databaseConnectionManager, this, queryContext);
     }
     
     private void failedIfBackendNotReady(final ConnectionSession connectionSession, final SQLStatementContext sqlStatementContext) {
@@ -170,9 +162,7 @@ public final class DatabaseConnector implements DatabaseBackendHandler {
     @Override
     public ResponseHeader execute() throws SQLException {
         MetaDataContexts metaDataContexts = ProxyContext.getInstance().getContextManager().getMetaDataContexts();
-        if (new SQLFederationDecideEngine(database.getRuleMetaData().getRules())
-                .decide(queryContext.getSqlStatementContext(), queryContext.getParameters(), database, metaDataContexts.getMetaData().getGlobalRuleMetaData())) {
-            prepareFederationExecutor();
+        if (proxySQLExecutor.getSqlFederationEngine().decide(queryContext.getSqlStatementContext(), queryContext.getParameters(), database, metaDataContexts.getMetaData().getGlobalRuleMetaData())) {
             ResultSet resultSet = doExecuteFederation(queryContext, metaDataContexts);
             return processExecuteFederation(resultSet, metaDataContexts);
         }
@@ -247,17 +237,6 @@ public final class DatabaseConnector implements DatabaseBackendHandler {
         return executeResultSample instanceof QueryResult ? processExecuteQuery(executionContext, result, (QueryResult) executeResultSample) : processExecuteUpdate(executionContext, result);
     }
     
-    private void prepareFederationExecutor() {
-        MetaDataContexts metaDataContexts = ProxyContext.getInstance().getContextManager().getMetaDataContexts();
-        String databaseName = databaseConnectionManager.getConnectionSession().getDatabaseName();
-        DatabaseType databaseType = queryContext.getSqlStatementContext().getDatabaseType();
-        String schemaName = queryContext.getSqlStatementContext().getTablesContext().getSchemaName().orElseGet(() -> DatabaseTypeEngine.getDefaultSchemaName(databaseType, databaseName));
-        SQLFederationRule sqlFederationRule = metaDataContexts.getMetaData().getGlobalRuleMetaData().getSingleRule(SQLFederationRule.class);
-        federationExecutor = sqlFederationRule.getSqlFederationExecutor();
-        federationExecutor.init(databaseName, schemaName, metaDataContexts.getMetaData(), metaDataContexts.getShardingSphereData(),
-                new JDBCExecutor(BackendExecutorContext.getInstance().getExecutorEngine(), databaseConnectionManager.getConnectionSession().getConnectionContext()));
-    }
-    
     private ResultSet doExecuteFederation(final QueryContext queryContext, final MetaDataContexts metaDataContexts) {
         boolean isReturnGeneratedKeys = queryContext.getSqlStatementContext().getSqlStatement() instanceof MySQLInsertStatement;
         ShardingSphereDatabase database = metaDataContexts.getMetaData().getDatabase(databaseConnectionManager.getConnectionSession().getDatabaseName());
@@ -267,7 +246,7 @@ public final class DatabaseConnector implements DatabaseBackendHandler {
                 queryContext.getSqlStatementContext().getSqlStatement(), this, isReturnGeneratedKeys, SQLExecutorExceptionHandler.isExceptionThrown(), true);
         DriverExecutionPrepareEngine<JDBCExecutionUnit, Connection> prepareEngine = createDriverExecutionPrepareEngine(isReturnGeneratedKeys, metaDataContexts);
         SQLFederationExecutorContext context = new SQLFederationExecutorContext(false, queryContext, metaDataContexts.getMetaData());
-        return federationExecutor.executeQuery(prepareEngine, callback, context);
+        return proxySQLExecutor.getSqlFederationEngine().executeQuery(prepareEngine, callback, context);
     }
     
     private DriverExecutionPrepareEngine<JDBCExecutionUnit, Connection> createDriverExecutionPrepareEngine(final boolean isReturnGeneratedKeys, final MetaDataContexts metaData) {
@@ -418,7 +397,7 @@ public final class DatabaseConnector implements DatabaseBackendHandler {
         Collection<SQLException> result = new LinkedList<>();
         result.addAll(closeResultSets());
         result.addAll(closeStatements());
-        closeFederationExecutor().ifPresent(result::add);
+        closeSQLFederationEngine().ifPresent(result::add);
         if (result.isEmpty()) {
             return;
         }
@@ -454,10 +433,10 @@ public final class DatabaseConnector implements DatabaseBackendHandler {
         return result;
     }
     
-    private Optional<SQLException> closeFederationExecutor() {
-        if (null != federationExecutor) {
+    private Optional<SQLException> closeSQLFederationEngine() {
+        if (null != proxySQLExecutor.getSqlFederationEngine()) {
             try {
-                federationExecutor.close();
+                proxySQLExecutor.getSqlFederationEngine().close();
             } catch (final SQLException ex) {
                 return Optional.of(ex);
             }
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/ProxySQLExecutor.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/ProxySQLExecutor.java
index c420775470b..182d508eda0 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/ProxySQLExecutor.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/connector/ProxySQLExecutor.java
@@ -17,12 +17,12 @@
 
 package org.apache.shardingsphere.proxy.backend.connector;
 
+import lombok.Getter;
 import org.apache.shardingsphere.dialect.exception.transaction.TableModifyInTransactionException;
 import org.apache.shardingsphere.infra.binder.type.TableAvailable;
 import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
-import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
-import org.apache.shardingsphere.infra.session.connection.transaction.TransactionConnectionContext;
 import org.apache.shardingsphere.infra.database.type.DatabaseType;
+import org.apache.shardingsphere.infra.database.type.DatabaseTypeEngine;
 import org.apache.shardingsphere.infra.executor.kernel.ExecutorEngine;
 import org.apache.shardingsphere.infra.executor.kernel.model.ExecutionGroupContext;
 import org.apache.shardingsphere.infra.executor.kernel.model.ExecutionGroupReportContext;
@@ -39,9 +39,13 @@ import org.apache.shardingsphere.infra.executor.sql.prepare.driver.jdbc.Statemen
 import org.apache.shardingsphere.infra.executor.sql.prepare.raw.RawExecutionPrepareEngine;
 import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
 import org.apache.shardingsphere.infra.rule.identifier.type.RawExecutionRule;
+import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
+import org.apache.shardingsphere.infra.session.connection.transaction.TransactionConnectionContext;
+import org.apache.shardingsphere.infra.session.query.QueryContext;
 import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
 import org.apache.shardingsphere.infra.util.spi.ShardingSphereServiceLoader;
 import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
 import org.apache.shardingsphere.proxy.backend.connector.jdbc.executor.ProxyJDBCExecutor;
 import org.apache.shardingsphere.proxy.backend.connector.jdbc.statement.JDBCBackendStatement;
 import org.apache.shardingsphere.proxy.backend.connector.sane.SaneQueryResultEngine;
@@ -59,6 +63,7 @@ import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQ
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.OpenGaussStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.ddl.OpenGaussCursorStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.PostgreSQLStatement;
+import org.apache.shardingsphere.sqlfederation.engine.SQLFederationEngine;
 import org.apache.shardingsphere.transaction.api.TransactionType;
 import org.apache.shardingsphere.transaction.spi.TransactionHook;
 
@@ -78,19 +83,28 @@ public final class ProxySQLExecutor {
     
     private final ProxyDatabaseConnectionManager databaseConnectionManager;
     
-    private final ProxyJDBCExecutor jdbcExecutor;
+    private final ProxyJDBCExecutor regularExecutor;
     
     private final RawExecutor rawExecutor;
     
+    @Getter
+    private final SQLFederationEngine sqlFederationEngine;
+    
     private final Collection<TransactionHook> transactionHooks = ShardingSphereServiceLoader.getServiceInstances(TransactionHook.class);
     
-    public ProxySQLExecutor(final String type, final ProxyDatabaseConnectionManager databaseConnectionManager, final DatabaseConnector databaseConnector) {
+    public ProxySQLExecutor(final String type, final ProxyDatabaseConnectionManager databaseConnectionManager, final DatabaseConnector databaseConnector, final QueryContext queryContext) {
         this.type = type;
         this.databaseConnectionManager = databaseConnectionManager;
         ExecutorEngine executorEngine = BackendExecutorContext.getInstance().getExecutorEngine();
         ConnectionContext connectionContext = databaseConnectionManager.getConnectionSession().getConnectionContext();
-        jdbcExecutor = new ProxyJDBCExecutor(type, databaseConnectionManager.getConnectionSession(), databaseConnector, new JDBCExecutor(executorEngine, connectionContext));
+        JDBCExecutor jdbcExecutor = new JDBCExecutor(executorEngine, connectionContext);
+        regularExecutor = new ProxyJDBCExecutor(type, databaseConnectionManager.getConnectionSession(), databaseConnector, jdbcExecutor);
         rawExecutor = new RawExecutor(executorEngine, connectionContext);
+        MetaDataContexts metaDataContexts = ProxyContext.getInstance().getContextManager().getMetaDataContexts();
+        String databaseName = databaseConnectionManager.getConnectionSession().getDatabaseName();
+        String schemaName = queryContext.getSqlStatementContext().getTablesContext().getSchemaName()
+                .orElseGet(() -> DatabaseTypeEngine.getDefaultSchemaName(queryContext.getSqlStatementContext().getDatabaseType(), databaseName));
+        sqlFederationEngine = new SQLFederationEngine(databaseName, schemaName, metaDataContexts.getMetaData(), metaDataContexts.getShardingSphereData(), jdbcExecutor);
     }
     
     /**
@@ -201,7 +215,7 @@ public final class ProxySQLExecutor {
             return getSaneExecuteResults(executionContext, ex);
         }
         executeTransactionHooksBeforeExecuteSQL(databaseConnectionManager.getConnectionSession());
-        return jdbcExecutor.execute(executionContext.getQueryContext(), executionGroupContext, isReturnGeneratedKeys, isExceptionThrown);
+        return regularExecutor.execute(executionContext.getQueryContext(), executionGroupContext, isReturnGeneratedKeys, isExceptionThrown);
     }
     
     private void executeTransactionHooksBeforeExecuteSQL(final ConnectionSession connectionSession) throws SQLException {
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/PreviewExecutor.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/PreviewExecutor.java
index 0bbd2e5c036..94a6215ed20 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/PreviewExecutor.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/PreviewExecutor.java
@@ -59,10 +59,8 @@ import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.executor.Conn
 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dml.MySQLInsertStatement;
-import org.apache.shardingsphere.sqlfederation.decider.SQLFederationDecideEngine;
-import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutor;
+import org.apache.shardingsphere.sqlfederation.engine.SQLFederationEngine;
 import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutorContext;
-import org.apache.shardingsphere.sqlfederation.rule.SQLFederationRule;
 
 import java.sql.Connection;
 import java.sql.SQLException;
@@ -103,8 +101,11 @@ public final class PreviewExecutor implements ConnectionSessionRequiredRULExecut
         ShardingSphereDatabase database = ProxyContext.getInstance().getDatabase(connectionSession.getDatabaseName());
         ShardingSpherePreconditions.checkState(database.isComplete(), () -> new RuleNotExistedException(connectionSession.getDatabaseName()));
         ConfigurationProperties props = metaDataContexts.getMetaData().getProps();
-        Collection<ExecutionUnit> executionUnits = isUseFederation(queryContext, database, metaDataContexts, connectionSession)
-                ? getFederationExecutionUnits(queryContext, databaseName, metaDataContexts, connectionSession)
+        String schemaName = queryContext.getSqlStatementContext().getTablesContext().getSchemaName().orElseGet(() -> DatabaseTypeEngine.getDefaultSchemaName(database.getProtocolType(), databaseName));
+        SQLFederationEngine sqlFederationEngine = new SQLFederationEngine(databaseName, schemaName, metaDataContexts.getMetaData(), metaDataContexts.getShardingSphereData(),
+                new JDBCExecutor(BackendExecutorContext.getInstance().getExecutorEngine(), connectionSession.getConnectionContext()));
+        Collection<ExecutionUnit> executionUnits = isUseFederation(queryContext, metaDataContexts, connectionSession, sqlFederationEngine)
+                ? getFederationExecutionUnits(queryContext, metaDataContexts, connectionSession, sqlFederationEngine)
                 : kernelProcessor.generateExecutionContext(queryContext, database, globalRuleMetaData, props, connectionSession.getConnectionContext()).getExecutionUnits();
         return executionUnits.stream().map(this::buildRow).collect(Collectors.toList());
     }
@@ -119,10 +120,9 @@ public final class PreviewExecutor implements ConnectionSessionRequiredRULExecut
         ((CursorDefinitionAware) sqlStatementContext).setUpCursorDefinition(cursorStatementContext);
     }
     
-    private boolean isUseFederation(final QueryContext queryContext, final ShardingSphereDatabase database, final MetaDataContexts metaDataContexts,
-                                    final ConnectionSession connectionSession) {
-        SQLFederationDecideEngine engine = new SQLFederationDecideEngine(database.getRuleMetaData().getRules());
-        return engine.decide(queryContext.getSqlStatementContext(), queryContext.getParameters(),
+    private boolean isUseFederation(final QueryContext queryContext, final MetaDataContexts metaDataContexts, final ConnectionSession connectionSession,
+                                    final SQLFederationEngine sqlFederationEngine) {
+        return sqlFederationEngine.decide(queryContext.getSqlStatementContext(), queryContext.getParameters(),
                 metaDataContexts.getMetaData().getDatabase(connectionSession.getDatabaseName()), metaDataContexts.getMetaData().getGlobalRuleMetaData());
     }
     
@@ -130,19 +130,14 @@ public final class PreviewExecutor implements ConnectionSessionRequiredRULExecut
         return new LocalDataQueryResultRow(unit.getDataSourceName(), unit.getSqlUnit().getSql());
     }
     
-    private Collection<ExecutionUnit> getFederationExecutionUnits(final QueryContext queryContext, final String databaseName, final MetaDataContexts metaDataContexts,
-                                                                  final ConnectionSession connectionSession) {
+    private Collection<ExecutionUnit> getFederationExecutionUnits(final QueryContext queryContext, final MetaDataContexts metaDataContexts,
+                                                                  final ConnectionSession connectionSession, final SQLFederationEngine sqlFederationEngine) {
         SQLStatement sqlStatement = queryContext.getSqlStatementContext().getSqlStatement();
         boolean isReturnGeneratedKeys = sqlStatement instanceof MySQLInsertStatement;
         DriverExecutionPrepareEngine<JDBCExecutionUnit, Connection> prepareEngine = createDriverExecutionPrepareEngine(isReturnGeneratedKeys, metaDataContexts, connectionSession);
         SQLFederationExecutorContext context = new SQLFederationExecutorContext(true, queryContext, metaDataContexts.getMetaData());
         ShardingSphereDatabase database = metaDataContexts.getMetaData().getDatabase(getDatabaseName(connectionSession));
-        String schemaName = queryContext.getSqlStatementContext().getTablesContext().getSchemaName().orElseGet(() -> DatabaseTypeEngine.getDefaultSchemaName(database.getProtocolType(), databaseName));
-        SQLFederationRule sqlFederationRule = metaDataContexts.getMetaData().getGlobalRuleMetaData().getSingleRule(SQLFederationRule.class);
-        SQLFederationExecutor sqlFederationExecutor = sqlFederationRule.getSqlFederationExecutor();
-        sqlFederationExecutor.init(databaseName, schemaName, metaDataContexts.getMetaData(), metaDataContexts.getShardingSphereData(),
-                new JDBCExecutor(BackendExecutorContext.getInstance().getExecutorEngine(), connectionSession.getConnectionContext()));
-        sqlFederationExecutor.executeQuery(prepareEngine, createPreviewFederationCallback(database.getProtocolType(), database.getResourceMetaData().getStorageTypes(), sqlStatement), context);
+        sqlFederationEngine.executeQuery(prepareEngine, createPreviewFederationCallback(database.getProtocolType(), database.getResourceMetaData().getStorageTypes(), sqlStatement), context);
         return context.getExecutionUnits();
     }
     
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnectorTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnectorTest.java
index b4dc4777437..6a563663047 100644
--- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnectorTest.java
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/DatabaseConnectorTest.java
@@ -19,15 +19,12 @@ package org.apache.shardingsphere.proxy.backend.connector;
 
 import lombok.SneakyThrows;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
-import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
 import org.apache.shardingsphere.infra.database.DefaultDatabase;
-import org.apache.shardingsphere.infra.database.type.DatabaseType;
 import org.apache.shardingsphere.infra.database.type.dialect.H2DatabaseType;
 import org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResult;
 import org.apache.shardingsphere.infra.executor.sql.execute.result.query.QueryResultMetaData;
-import org.apache.shardingsphere.infra.executor.sql.prepare.driver.DriverExecutionPrepareEngine;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryMergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.memory.MemoryQueryResultRow;
 import org.apache.shardingsphere.infra.metadata.ShardingSphereMetaData;
@@ -46,18 +43,12 @@ import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
 import org.apache.shardingsphere.parser.config.SQLParserRuleConfiguration;
 import org.apache.shardingsphere.parser.rule.SQLParserRule;
-import org.apache.shardingsphere.proxy.backend.connector.jdbc.executor.callback.ProxyJDBCExecutorCallback;
 import org.apache.shardingsphere.proxy.backend.connector.jdbc.fixture.QueryHeaderBuilderFixture;
-import org.apache.shardingsphere.proxy.backend.connector.jdbc.statement.JDBCBackendStatement;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
-import org.apache.shardingsphere.proxy.backend.response.data.QueryResponseRow;
 import org.apache.shardingsphere.proxy.backend.response.header.query.QueryHeaderBuilder;
 import org.apache.shardingsphere.proxy.backend.response.header.query.QueryHeaderBuilderEngine;
 import org.apache.shardingsphere.sharding.rule.ShardingRule;
 import org.apache.shardingsphere.sql.parser.api.CacheOption;
-import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutor;
-import org.apache.shardingsphere.sqlfederation.executor.SQLFederationExecutorContext;
-import org.apache.shardingsphere.sqlfederation.optimizer.context.parser.dialect.OptimizerSQLDialectBuilder;
 import org.apache.shardingsphere.sqlfederation.rule.SQLFederationRule;
 import org.apache.shardingsphere.test.mock.AutoMockExtension;
 import org.apache.shardingsphere.test.mock.StaticMockSettings;
@@ -88,7 +79,6 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
@@ -141,35 +131,6 @@ class DatabaseConnectorTest {
         return Collections.singletonMap("foo_db", database);
     }
     
-    @Test
-    void assertExecuteFederationAndClose() throws SQLException {
-        SQLStatementContext sqlStatementContext = mock(SelectStatementContext.class, RETURNS_DEEP_STUBS);
-        when(sqlStatementContext.getDatabaseType()).thenReturn(new MySQLDatabaseType());
-        DatabaseConnector engine =
-                DatabaseConnectorFactory.getInstance().newInstance(new QueryContext(sqlStatementContext, "schemaName", Collections.emptyList()), databaseConnectionManager, true);
-        when(databaseConnectionManager.getConnectionSession().getStatementManager()).thenReturn(new JDBCBackendStatement());
-        SQLFederationExecutor federationExecutor = mock(SQLFederationExecutor.class);
-        when(sqlFederationRule.getSqlFederationExecutor()).thenReturn(federationExecutor);
-        when(SystemSchemaUtils.containsSystemSchema(any(DatabaseType.class), any(), any(ShardingSphereDatabase.class))).thenReturn(true);
-        try (MockedStatic<TypedSPILoader> typedSPILoader = mockStatic(TypedSPILoader.class)) {
-            typedSPILoader.when(() -> TypedSPILoader.getService(QueryHeaderBuilder.class, "H2")).thenReturn(new QueryHeaderBuilderFixture());
-            typedSPILoader.when(() -> TypedSPILoader.getService(OptimizerSQLDialectBuilder.class, "MySQL")).thenReturn(mock(OptimizerSQLDialectBuilder.class));
-            typedSPILoader.when(() -> TypedSPILoader.getService(DatabaseType.class, "H2")).thenReturn(new MySQLDatabaseType());
-            when(federationExecutor.executeQuery(any(DriverExecutionPrepareEngine.class), any(ProxyJDBCExecutorCallback.class), any(SQLFederationExecutorContext.class))).thenReturn(resultSet);
-            when(resultSet.getMetaData().getColumnCount()).thenReturn(1);
-            when(resultSet.next()).thenReturn(true, false);
-            when(resultSet.getObject(1)).thenReturn(Integer.MAX_VALUE);
-            engine.execute();
-        }
-        assertTrue(engine.next());
-        QueryResponseRow actualRow = engine.getRowData();
-        assertThat(actualRow.getCells().get(0).getJdbcType(), is(Types.INTEGER));
-        assertThat(actualRow.getCells().get(0).getData(), is(Integer.MAX_VALUE));
-        assertFalse(engine.next());
-        engine.close();
-        verify(federationExecutor).close();
-    }
-    
     @Test
     void assertBinaryProtocolQueryHeader() throws SQLException, NoSuchFieldException, IllegalAccessException {
         SQLStatementContext sqlStatementContext = mock(SQLStatementContext.class, RETURNS_DEEP_STUBS);
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/ProxySQLExecutorTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/ProxySQLExecutorTest.java
index 32e0ed4625d..e035b0a5c3c 100644
--- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/ProxySQLExecutorTest.java
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/connector/ProxySQLExecutorTest.java
@@ -18,7 +18,6 @@
 package org.apache.shardingsphere.proxy.backend.connector;
 
 import org.apache.shardingsphere.dialect.exception.transaction.TableModifyInTransactionException;
-import org.apache.shardingsphere.infra.session.query.QueryContext;
 import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
 import org.apache.shardingsphere.infra.binder.statement.ddl.CreateTableStatementContext;
 import org.apache.shardingsphere.infra.binder.statement.ddl.CursorStatementContext;
@@ -26,7 +25,9 @@ import org.apache.shardingsphere.infra.binder.statement.ddl.TruncateStatementCon
 import org.apache.shardingsphere.infra.binder.statement.dml.InsertStatementContext;
 import org.apache.shardingsphere.infra.binder.statement.dml.SelectStatementContext;
 import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
+import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
 import org.apache.shardingsphere.infra.database.DefaultDatabase;
+import org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType;
 import org.apache.shardingsphere.infra.executor.sql.context.ExecutionContext;
 import org.apache.shardingsphere.infra.executor.sql.prepare.driver.jdbc.JDBCDriverType;
 import org.apache.shardingsphere.infra.instance.InstanceContext;
@@ -35,9 +36,10 @@ import org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
 import org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import org.apache.shardingsphere.infra.route.context.RouteContext;
+import org.apache.shardingsphere.infra.session.query.QueryContext;
+import org.apache.shardingsphere.metadata.persist.MetaDataPersistService;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
-import org.apache.shardingsphere.metadata.persist.MetaDataPersistService;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
 import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionsSegment;
@@ -53,6 +55,7 @@ import org.apache.shardingsphere.sql.parser.sql.dialect.statement.opengauss.ddl.
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.ddl.PostgreSQLCreateTableStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.ddl.PostgreSQLTruncateStatement;
 import org.apache.shardingsphere.sql.parser.sql.dialect.statement.postgresql.dml.PostgreSQLInsertStatement;
+import org.apache.shardingsphere.sqlfederation.rule.SQLFederationRule;
 import org.apache.shardingsphere.test.mock.AutoMockExtension;
 import org.apache.shardingsphere.test.mock.StaticMockSettings;
 import org.apache.shardingsphere.transaction.api.TransactionType;
@@ -65,6 +68,7 @@ import org.mockito.junit.jupiter.MockitoSettings;
 import org.mockito.quality.Strictness;
 
 import java.util.Collections;
+import java.util.Optional;
 
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
@@ -79,7 +83,7 @@ class ProxySQLExecutorTest {
     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private ConnectionSession connectionSession;
     
-    @Mock
+    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     private ProxyDatabaseConnectionManager databaseConnectionManager;
     
     @BeforeEach
@@ -88,7 +92,12 @@ class ProxySQLExecutorTest {
         when(connectionSession.getTransactionStatus().isInTransaction()).thenReturn(true);
         when(connectionSession.getDatabaseConnectionManager()).thenReturn(databaseConnectionManager);
         when(databaseConnectionManager.getConnectionSession()).thenReturn(connectionSession);
-        ContextManager contextManager = new ContextManager(new MetaDataContexts(mock(MetaDataPersistService.class), new ShardingSphereMetaData()), mock(InstanceContext.class));
+        when(databaseConnectionManager.getConnectionSession().getDatabaseName()).thenReturn(DefaultDatabase.LOGIC_NAME);
+        ShardingSphereMetaData metaData = mock(ShardingSphereMetaData.class, RETURNS_DEEP_STUBS);
+        when(metaData.getDatabase(DefaultDatabase.LOGIC_NAME)).thenReturn(mock(ShardingSphereDatabase.class, RETURNS_DEEP_STUBS));
+        when(metaData.getProps().<Integer>getValue(ConfigurationPropertyKey.KERNEL_EXECUTOR_SIZE)).thenReturn(0);
+        when(metaData.getGlobalRuleMetaData()).thenReturn(new ShardingSphereRuleMetaData(Collections.singletonList(mock(SQLFederationRule.class))));
+        ContextManager contextManager = new ContextManager(new MetaDataContexts(mock(MetaDataPersistService.class), metaData), mock(InstanceContext.class));
         when(ProxyContext.getInstance().getContextManager()).thenReturn(contextManager);
     }
     
@@ -97,7 +106,7 @@ class ProxySQLExecutorTest {
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createMySQLCreateTableStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
         assertThrows(TableModifyInTransactionException.class,
-                () -> new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext));
+                () -> new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext));
     }
     
     @Test
@@ -105,7 +114,7 @@ class ProxySQLExecutorTest {
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createMySQLTruncateStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
         assertThrows(TableModifyInTransactionException.class,
-                () -> new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext));
+                () -> new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext));
     }
     
     @Test
@@ -113,14 +122,14 @@ class ProxySQLExecutorTest {
         when(connectionSession.getTransactionStatus().getTransactionType()).thenReturn(TransactionType.LOCAL);
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createMySQLTruncateStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
-        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext);
+        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext);
     }
     
     @Test
     void assertCheckExecutePrerequisitesWhenExecuteDMLInXATransaction() {
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createMySQLInsertStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
-        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext);
+        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext);
     }
     
     @Test
@@ -128,7 +137,7 @@ class ProxySQLExecutorTest {
         when(connectionSession.getTransactionStatus().getTransactionType()).thenReturn(TransactionType.BASE);
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createMySQLCreateTableStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
-        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext);
+        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext);
     }
     
     @Test
@@ -136,7 +145,7 @@ class ProxySQLExecutorTest {
         when(connectionSession.getTransactionStatus().isInTransaction()).thenReturn(false);
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createMySQLCreateTableStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
-        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext);
+        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext);
     }
     
     @Test
@@ -145,7 +154,7 @@ class ProxySQLExecutorTest {
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createPostgreSQLCreateTableStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
         assertThrows(TableModifyInTransactionException.class,
-                () -> new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext));
+                () -> new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext));
     }
     
     @Test
@@ -153,7 +162,7 @@ class ProxySQLExecutorTest {
         when(connectionSession.getTransactionStatus().getTransactionType()).thenReturn(TransactionType.LOCAL);
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createPostgreSQLTruncateStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
-        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext);
+        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext);
     }
     
     @Test
@@ -161,7 +170,7 @@ class ProxySQLExecutorTest {
         when(connectionSession.getTransactionStatus().getTransactionType()).thenReturn(TransactionType.LOCAL);
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createCursorStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
-        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext);
+        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext);
     }
     
     @Test
@@ -169,7 +178,7 @@ class ProxySQLExecutorTest {
         when(connectionSession.getTransactionStatus().getTransactionType()).thenReturn(TransactionType.LOCAL);
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createPostgreSQLInsertStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
-        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext);
+        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext);
     }
     
     @Test
@@ -177,7 +186,14 @@ class ProxySQLExecutorTest {
         when(connectionSession.getTransactionStatus().getTransactionType()).thenReturn(TransactionType.LOCAL);
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createMySQLCreateTableStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
-        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext);
+        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext);
+    }
+    
+    private QueryContext mockQueryContext() {
+        QueryContext result = mock(QueryContext.class, RETURNS_DEEP_STUBS);
+        when(result.getSqlStatementContext().getDatabaseType()).thenReturn(new MySQLDatabaseType());
+        when(result.getSqlStatementContext().getTablesContext().getSchemaName()).thenReturn(Optional.of(DefaultDatabase.LOGIC_NAME));
+        return result;
     }
     
     @Test
@@ -186,7 +202,7 @@ class ProxySQLExecutorTest {
         when(connectionSession.getTransactionStatus().isInTransaction()).thenReturn(false);
         ExecutionContext executionContext = new ExecutionContext(
                 new QueryContext(createPostgreSQLCreateTableStatementContext(), "", Collections.emptyList()), Collections.emptyList(), mock(RouteContext.class));
-        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class)).checkExecutePrerequisites(executionContext);
+        new ProxySQLExecutor(JDBCDriverType.STATEMENT, databaseConnectionManager, mock(DatabaseConnector.class), mockQueryContext()).checkExecutePrerequisites(executionContext);
     }
     
     private CreateTableStatementContext createMySQLCreateTableStatementContext() {