You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by ji...@apache.org on 2023/05/25 04:26:28 UTC

[shardingsphere] branch master updated: Add RULExecutor and refactor RULBackendHandlerFactory (#25873)

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

jianglongtao 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 daf7960dc23 Add RULExecutor and refactor RULBackendHandlerFactory (#25873)
daf7960dc23 is described below

commit daf7960dc237c9bb620d040708dfb8b83ccb0ccb
Author: yx9o <ya...@163.com>
AuthorDate: Thu May 25 12:26:21 2023 +0800

    Add RULExecutor and refactor RULBackendHandlerFactory (#25873)
    
    * Add RULExecutor and refactor RULBackendHandlerFactory
    
    * Update
---
 ...dler.java => AbstractSQLRULBackendHandler.java} |  7 +--
 .../distsql/rul/RULBackendHandlerFactory.java      | 10 ++--
 .../handler/distsql/rul/SQLRULBackendHandler.java  | 35 ++++++-------
 .../handler/distsql/rul/executor/RULExecutor.java  | 54 ++++++++++++++++++++
 ...ormatSQLHandler.java => FormatSQLExecutor.java} | 25 +++++-----
 .../distsql/rul/sql/ParseDistSQLHandler.java       |  4 +-
 .../handler/distsql/rul/sql/PreviewHandler.java    |  4 +-
 ...ackend.handler.distsql.rul.executor.RULExecutor | 18 +++++++
 .../handler/ProxyBackendHandlerFactoryTest.java    |  6 +--
 .../distsql/rul/sql/FormatSQLExecutorTest.java     | 57 ++++++++++++++++++++++
 10 files changed, 175 insertions(+), 45 deletions(-)

diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/SQLRULBackendHandler.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/AbstractSQLRULBackendHandler.java
similarity index 94%
copy from proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/SQLRULBackendHandler.java
copy to proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/AbstractSQLRULBackendHandler.java
index 7f0c0f7d195..676a175ddf8 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/SQLRULBackendHandler.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/AbstractSQLRULBackendHandler.java
@@ -38,10 +38,11 @@ import java.util.stream.Collectors;
 
 /**
  * SQL RUL backend handler.
- * 
- * @param <E> type of RUL statement
+ * TODO Remove this class when #25868 is done
+ *
+ * @param <T> type of RUL statement
  */
-public abstract class SQLRULBackendHandler<E extends RULStatement> extends RULBackendHandler<E> {
+public abstract class AbstractSQLRULBackendHandler<T extends RULStatement> extends RULBackendHandler<T> {
     
     private List<QueryHeader> queryHeaders;
     
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/RULBackendHandlerFactory.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/RULBackendHandlerFactory.java
index 294da2bf451..367593d23c7 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/RULBackendHandlerFactory.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/RULBackendHandlerFactory.java
@@ -20,13 +20,13 @@ package org.apache.shardingsphere.proxy.backend.handler.distsql.rul;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.apache.shardingsphere.distsql.parser.statement.rul.RULStatement;
-import org.apache.shardingsphere.distsql.parser.statement.rul.sql.FormatStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rul.sql.ParseStatement;
 import org.apache.shardingsphere.distsql.parser.statement.rul.sql.PreviewStatement;
 import org.apache.shardingsphere.infra.util.exception.ShardingSpherePreconditions;
 import org.apache.shardingsphere.infra.util.exception.external.sql.type.generic.UnsupportedSQLOperationException;
+import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.proxy.backend.handler.ProxyBackendHandler;
-import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.sql.FormatSQLHandler;
+import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.executor.RULExecutor;
 import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.sql.ParseDistSQLHandler;
 import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.sql.PreviewHandler;
 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
@@ -45,7 +45,6 @@ public final class RULBackendHandlerFactory {
     static {
         HANDLERS.put(ParseStatement.class, ParseDistSQLHandler.class);
         HANDLERS.put(PreviewStatement.class, PreviewHandler.class);
-        HANDLERS.put(FormatStatement.class, FormatSQLHandler.class);
     }
     
     /**
@@ -56,6 +55,11 @@ public final class RULBackendHandlerFactory {
      * @return created instance
      */
     public static ProxyBackendHandler newInstance(final RULStatement sqlStatement, final ConnectionSession connectionSession) {
+        if (TypedSPILoader.contains(RULExecutor.class, sqlStatement.getClass().getName())) {
+            RULBackendHandler<?> result = new SQLRULBackendHandler<>();
+            result.init(sqlStatement, connectionSession);
+            return result;
+        }
         return createRULBackendHandler(sqlStatement, connectionSession);
     }
     
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/SQLRULBackendHandler.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/SQLRULBackendHandler.java
index 7f0c0f7d195..89b45576b07 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/SQLRULBackendHandler.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/SQLRULBackendHandler.java
@@ -20,9 +20,8 @@ package org.apache.shardingsphere.proxy.backend.handler.distsql.rul;
 import org.apache.shardingsphere.distsql.parser.statement.rul.RULStatement;
 import org.apache.shardingsphere.infra.merge.result.MergedResult;
 import org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataMergedResult;
-import org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
-import org.apache.shardingsphere.mode.manager.ContextManager;
-import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPILoader;
+import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.executor.RULExecutor;
 import org.apache.shardingsphere.proxy.backend.response.data.QueryResponseCell;
 import org.apache.shardingsphere.proxy.backend.response.data.QueryResponseRow;
 import org.apache.shardingsphere.proxy.backend.response.header.ResponseHeader;
@@ -32,51 +31,47 @@ import org.apache.shardingsphere.proxy.backend.response.header.query.QueryRespon
 import java.sql.SQLException;
 import java.sql.Types;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 
 /**
  * SQL RUL backend handler.
- * 
- * @param <E> type of RUL statement
+ *
+ * @param <T> type of RUL statement
  */
-public abstract class SQLRULBackendHandler<E extends RULStatement> extends RULBackendHandler<E> {
+public final class SQLRULBackendHandler<T extends RULStatement> extends RULBackendHandler<T> {
     
     private List<QueryHeader> queryHeaders;
     
     private MergedResult mergedResult;
     
     @Override
-    public final ResponseHeader execute() throws SQLException {
-        queryHeaders = createQueryHeader();
-        mergedResult = createMergedResult();
+    public ResponseHeader execute() {
+        RULExecutor<T> executor = TypedSPILoader.getService(RULExecutor.class, getSqlStatement().getClass().getName());
+        queryHeaders = createQueryHeader(executor);
+        mergedResult = createMergedResult(executor);
         return new QueryResponseHeader(queryHeaders);
     }
     
-    private List<QueryHeader> createQueryHeader() {
-        return getColumnNames().stream().map(each -> new QueryHeader("", "", each, each, Types.CHAR, "CHAR", 255, 0, false, false, false, false)).collect(Collectors.toList());
+    private List<QueryHeader> createQueryHeader(final RULExecutor<T> executor) {
+        return executor.getColumnNames().stream().map(each -> new QueryHeader("", "", each, each, Types.CHAR, "CHAR", 255, 0, false, false, false, false)).collect(Collectors.toList());
     }
     
-    private MergedResult createMergedResult() throws SQLException {
-        return new LocalDataMergedResult(getRows(ProxyContext.getInstance().getContextManager()));
+    private MergedResult createMergedResult(final RULExecutor<T> executor) {
+        return new LocalDataMergedResult(executor.getRows(getConnectionSession(), getSqlStatement()));
     }
     
     @Override
-    public final boolean next() throws SQLException {
+    public boolean next() throws SQLException {
         return null != mergedResult && mergedResult.next();
     }
     
     @Override
-    public final QueryResponseRow getRowData() throws SQLException {
+    public QueryResponseRow getRowData() throws SQLException {
         List<QueryResponseCell> cells = new ArrayList<>(queryHeaders.size());
         for (int i = 0; i < queryHeaders.size(); i++) {
             cells.add(new QueryResponseCell(queryHeaders.get(i).getColumnType(), mergedResult.getValue(i + 1, Object.class)));
         }
         return new QueryResponseRow(cells);
     }
-    
-    protected abstract Collection<String> getColumnNames();
-    
-    protected abstract Collection<LocalDataQueryResultRow> getRows(ContextManager contextManager) throws SQLException;
 }
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/executor/RULExecutor.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/executor/RULExecutor.java
new file mode 100644
index 00000000000..9e3dd0f69d1
--- /dev/null
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/executor/RULExecutor.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.proxy.backend.handler.distsql.rul.executor;
+
+import org.apache.shardingsphere.distsql.parser.statement.rul.RULStatement;
+import org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
+import org.apache.shardingsphere.infra.util.spi.annotation.SingletonSPI;
+import org.apache.shardingsphere.infra.util.spi.type.typed.TypedSPI;
+import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * RUL executor.
+ *
+ * @param <T> type of RUL statement
+ */
+@SingletonSPI
+public interface RULExecutor<T extends RULStatement> extends TypedSPI {
+    
+    /**
+     * Get column names.
+     *
+     * @return column names
+     */
+    Collection<String> getColumnNames();
+    
+    /**
+     * Get query result rows.
+     *
+     * @param connectionSession connectionSession connection session
+     * @param sqlStatement SQL statement
+     * @return query result rows
+     */
+    default Collection<LocalDataQueryResultRow> getRows(ConnectionSession connectionSession, T sqlStatement) {
+        return Collections.emptyList();
+    }
+}
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/FormatSQLHandler.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/FormatSQLExecutor.java
similarity index 73%
rename from proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/FormatSQLHandler.java
rename to proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/FormatSQLExecutor.java
index 7c9fc1c906f..8ff2ffc01a4 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/FormatSQLHandler.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/FormatSQLExecutor.java
@@ -19,8 +19,8 @@ package org.apache.shardingsphere.proxy.backend.handler.distsql.rul.sql;
 
 import org.apache.shardingsphere.distsql.parser.statement.rul.sql.FormatStatement;
 import org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
-import org.apache.shardingsphere.mode.manager.ContextManager;
-import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.SQLRULBackendHandler;
+import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.executor.RULExecutor;
+import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
 import org.apache.shardingsphere.sql.parser.api.CacheOption;
 import org.apache.shardingsphere.sql.parser.api.SQLFormatEngine;
 
@@ -29,22 +29,18 @@ import java.util.Collections;
 import java.util.Properties;
 
 /**
- * Format SQL handler.
+ * Format SQL executor.
  */
-public final class FormatSQLHandler extends SQLRULBackendHandler<FormatStatement> {
-    
-    private static final String FORMATTED_RESULT = "formatted_result";
+public final class FormatSQLExecutor implements RULExecutor<FormatStatement> {
     
     @Override
-    protected Collection<String> getColumnNames() {
-        return Collections.singleton(FORMATTED_RESULT);
+    public Collection<String> getColumnNames() {
+        return Collections.singleton("formatted_result");
     }
     
     @Override
-    protected Collection<LocalDataQueryResultRow> getRows(final ContextManager contextManager) {
-        String sql = getSqlStatement().getSql();
-        String databaseType = getConnectionSession().getProtocolType().getType();
-        return Collections.singleton(new LocalDataQueryResultRow(formatSQL(sql, databaseType)));
+    public Collection<LocalDataQueryResultRow> getRows(final ConnectionSession connectionSession, final FormatStatement sqlStatement) {
+        return Collections.singleton(new LocalDataQueryResultRow(formatSQL(sqlStatement.getSql(), connectionSession.getProtocolType().getType())));
     }
     
     private Object formatSQL(final String sql, final String databaseType) {
@@ -52,4 +48,9 @@ public final class FormatSQLHandler extends SQLRULBackendHandler<FormatStatement
         props.setProperty("parameterized", Boolean.FALSE.toString());
         return new SQLFormatEngine(databaseType, new CacheOption(1, 1L)).format(sql, false, props);
     }
+    
+    @Override
+    public String getType() {
+        return FormatStatement.class.getName();
+    }
 }
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/ParseDistSQLHandler.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/ParseDistSQLHandler.java
index 9e617ba5457..1e8f1697e7c 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/ParseDistSQLHandler.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/ParseDistSQLHandler.java
@@ -22,7 +22,7 @@ import org.apache.shardingsphere.distsql.parser.statement.rul.sql.ParseStatement
 import org.apache.shardingsphere.infra.merge.result.impl.local.LocalDataQueryResultRow;
 import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.parser.rule.SQLParserRule;
-import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.SQLRULBackendHandler;
+import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.AbstractSQLRULBackendHandler;
 import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
 
 import java.util.Arrays;
@@ -32,7 +32,7 @@ import java.util.Collections;
 /**
  * Parse DistSQL handler.
  */
-public final class ParseDistSQLHandler extends SQLRULBackendHandler<ParseStatement> {
+public final class ParseDistSQLHandler extends AbstractSQLRULBackendHandler<ParseStatement> {
     
     private static final String PARSED_STATEMENT = "parsed_statement";
     
diff --git a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/PreviewHandler.java b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/PreviewHandler.java
index 1979f4bb7eb..83502bd9096 100644
--- a/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/PreviewHandler.java
+++ b/proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/PreviewHandler.java
@@ -56,7 +56,7 @@ import org.apache.shardingsphere.proxy.backend.connector.jdbc.statement.JDBCBack
 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.handler.distsql.rul.SQLRULBackendHandler;
+import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.AbstractSQLRULBackendHandler;
 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.rule.SQLFederationRule;
@@ -76,7 +76,7 @@ import java.util.stream.Collectors;
 /**
  * Preview handler.
  */
-public final class PreviewHandler extends SQLRULBackendHandler<PreviewStatement> {
+public final class PreviewHandler extends AbstractSQLRULBackendHandler<PreviewStatement> {
     
     private static final String DATA_SOURCE_NAME = "data_source_name";
     
diff --git a/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.handler.distsql.rul.executor.RULExecutor b/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.handler.distsql.rul.executor.RULExecutor
new file mode 100644
index 00000000000..b03229ac599
--- /dev/null
+++ b/proxy/backend/core/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.handler.distsql.rul.executor.RULExecutor
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+org.apache.shardingsphere.proxy.backend.handler.distsql.rul.sql.FormatSQLExecutor
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
index d2f00afe58c..87e2bae59c4 100644
--- a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/ProxyBackendHandlerFactoryTest.java
@@ -31,15 +31,15 @@ import org.apache.shardingsphere.mode.manager.ContextManager;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
 import org.apache.shardingsphere.parser.rule.SQLParserRule;
 import org.apache.shardingsphere.parser.rule.builder.DefaultSQLParserRuleConfigurationBuilder;
-import org.apache.shardingsphere.proxy.backend.connector.ProxyDatabaseConnectionManager;
 import org.apache.shardingsphere.proxy.backend.connector.DatabaseConnector;
+import org.apache.shardingsphere.proxy.backend.connector.ProxyDatabaseConnectionManager;
 import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
 import org.apache.shardingsphere.proxy.backend.handler.admin.DatabaseAdminQueryBackendHandler;
 import org.apache.shardingsphere.proxy.backend.handler.data.impl.UnicastDatabaseBackendHandler;
 import org.apache.shardingsphere.proxy.backend.handler.distsql.ral.QueryableRALBackendHandler;
 import org.apache.shardingsphere.proxy.backend.handler.distsql.ral.UpdatableRALBackendHandler;
 import org.apache.shardingsphere.proxy.backend.handler.distsql.rql.RQLBackendHandler;
-import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.SQLRULBackendHandler;
+import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.sql.PreviewHandler;
 import org.apache.shardingsphere.proxy.backend.handler.skip.SkipBackendHandler;
 import org.apache.shardingsphere.proxy.backend.handler.transaction.TransactionBackendHandler;
 import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
@@ -249,6 +249,6 @@ class ProxyBackendHandlerFactoryTest {
         when(connectionSession.getTransactionStatus().isInTransaction()).thenReturn(true);
         String sql = "PREVIEW INSERT INTO account VALUES(1, 1, 1)";
         ProxyBackendHandler actual = ProxyBackendHandlerFactory.newInstance(databaseType, sql, connectionSession);
-        assertThat(actual, instanceOf(SQLRULBackendHandler.class));
+        assertThat(actual, instanceOf(PreviewHandler.class));
     }
 }
diff --git a/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/FormatSQLExecutorTest.java b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/FormatSQLExecutorTest.java
new file mode 100644
index 00000000000..ebc6a525246
--- /dev/null
+++ b/proxy/backend/core/src/test/java/org/apache/shardingsphere/proxy/backend/handler/distsql/rul/sql/FormatSQLExecutorTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.proxy.backend.handler.distsql.rul.sql;
+
+import org.apache.shardingsphere.distsql.parser.statement.rul.sql.FormatStatement;
+import org.apache.shardingsphere.infra.database.type.dialect.MySQLDatabaseType;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.RULBackendHandler;
+import org.apache.shardingsphere.proxy.backend.handler.distsql.rul.SQLRULBackendHandler;
+import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
+import org.apache.shardingsphere.test.mock.StaticMockSettings;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+
+import java.sql.SQLException;
+import java.util.LinkedList;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.Mockito.when;
+
+@StaticMockSettings(ProxyContext.class)
+class FormatSQLExecutorTest {
+    
+    @Mock
+    private ConnectionSession connectionSession;
+    
+    @Test
+    void assertExecute() throws SQLException {
+        String sql = "SELECT * FROM t_order WHERE order_id=1";
+        when(connectionSession.getProtocolType()).thenReturn(new MySQLDatabaseType());
+        FormatStatement statement = new FormatStatement(sql);
+        RULBackendHandler<FormatStatement> handler = new SQLRULBackendHandler<>();
+        handler.init(statement, connectionSession);
+        handler.execute();
+        handler.next();
+        assertThat(new LinkedList<>(handler.getRowData().getData()).getFirst(), is("SELECT * \n"
+                + "FROM t_order\n"
+                + "WHERE \n"
+                + "\torder_id = 1;"));
+    }
+}