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;"));
+ }
+}