You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2022/07/12 09:19:50 UTC
[shardingsphere] branch master updated: Use SPI to handle MySQL SET statement behaviour (#19060)
This is an automated email from the ASF dual-hosted git repository.
zhangliang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 127b59af6bd Use SPI to handle MySQL SET statement behaviour (#19060)
127b59af6bd is described below
commit 127b59af6bd4f7f0f7408413872c4fd29a343808
Author: 吴伟杰 <wu...@apache.org>
AuthorDate: Tue Jul 12 17:19:44 2022 +0800
Use SPI to handle MySQL SET statement behaviour (#19060)
* Use SPI to handle MySQL SET variable behaviour
* Add test for MySQLSetVariableAdminExecutor
* Add MySQLSessionVariableHandlerFactoryTest
* Fix checkstyle in MySQLSessionVariableHandlerFactoryTest
* Complete TextProtocolBackendHandlerFactoryTest
---
...ava => DefaultMySQLSessionVariableHandler.java} | 24 +++---
.../admin/mysql/MySQLAdminExecutorCreator.java | 16 +---
...cutor.java => MySQLSessionVariableHandler.java} | 25 ++----
.../mysql/MySQLSessionVariableHandlerFactory.java | 48 +++++++++++
.../admin/mysql/MySQLSetVariableAdminExecutor.java | 92 ++++++++++++++++++++++
.../mysql/executor/MySQLSetCharsetExecutor.java | 40 +++++++---
.../text/data/DatabaseBackendHandlerFactory.java | 1 -
...nd.text.admin.mysql.MySQLSessionVariableHandler | 18 +++++
.../TextProtocolBackendHandlerFactoryTest.java | 12 ---
.../MySQLSessionVariableHandlerFactoryTest.java} | 33 ++++----
.../mysql/MySQLSetVariableAdminExecutorTest.java | 80 +++++++++++++++++++
.../mysql/TestFixtureSessionVariableHandler.java} | 25 +++---
...nd.text.admin.mysql.MySQLSessionVariableHandler | 18 +++++
13 files changed, 330 insertions(+), 102 deletions(-)
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/DefaultMySQLSessionVariableHandler.java
similarity index 61%
copy from shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java
copy to shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/DefaultMySQLSessionVariableHandler.java
index 847ac040492..ac076292710 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/DefaultMySQLSessionVariableHandler.java
@@ -15,27 +15,25 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor;
+package org.apache.shardingsphere.proxy.backend.text.admin.mysql;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
-import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutor;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatement;
-import java.sql.SQLException;
+import java.util.stream.Collectors;
/**
- * No Resource set executor.
+ * Default session variable handler for MySQL.
*/
-@Getter
-@RequiredArgsConstructor
-public final class NoResourceSetExecutor implements DatabaseAdminExecutor {
-
- private final SetStatement sqlStatement;
+@Slf4j
+public final class DefaultMySQLSessionVariableHandler implements MySQLSessionVariableHandler {
@Override
- public void execute(final ConnectionSession connectionSession) throws SQLException {
- return;
+ public void handle(final ConnectionSession connectionSession, final SetStatement setStatement) {
+ if (log.isDebugEnabled()) {
+ log.debug("Set statement {} was discarded.", setStatement.getVariableAssigns().stream()
+ .map(segment -> String.format("%s %s = %s", segment.getVariable().getScope(), segment.getVariable().getVariable(), segment.getAssignValue())).collect(Collectors.joining(", ")));
+ }
}
}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLAdminExecutorCreator.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLAdminExecutorCreator.java
index 829b24e061f..c835a7dbfdf 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLAdminExecutorCreator.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLAdminExecutorCreator.java
@@ -22,8 +22,6 @@ import org.apache.shardingsphere.infra.config.props.ConfigurationPropertyKey;
import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutor;
import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutorCreator;
-import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.MySQLSetCharsetExecutor;
-import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.NoResourceSetExecutor;
import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.NoResourceShowExecutor;
import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.ShowConnectionIdExecutor;
import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.ShowCreateDatabaseExecutor;
@@ -38,7 +36,6 @@ import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.ShowTra
import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.ShowVersionExecutor;
import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.UnicastResourceShowExecutor;
import org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor.UseDatabaseExecutor;
-import org.apache.shardingsphere.sql.parser.sql.common.segment.dal.VariableAssignSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ExpressionProjectionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dml.item.ProjectionSegment;
import org.apache.shardingsphere.sql.parser.sql.common.segment.generic.table.SimpleTableSegment;
@@ -54,7 +51,6 @@ import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQ
import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLShowProcessListStatement;
import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLShowTablesStatement;
-import java.util.Iterator;
import java.util.Optional;
/**
@@ -97,12 +93,7 @@ public final class MySQLAdminExecutorCreator implements DatabaseAdminExecutorCre
return Optional.of(new ShowCreateDatabaseExecutor((MySQLShowCreateDatabaseStatement) sqlStatement));
}
if (sqlStatement instanceof SetStatement) {
- if (!hasDatabases() || !hasResources()) {
- return Optional.of(new NoResourceSetExecutor((SetStatement) sqlStatement));
- }
- if (isSetClientEncoding((SetStatement) sqlStatement)) {
- return Optional.of(new MySQLSetCharsetExecutor((SetStatement) sqlStatement));
- }
+ return Optional.of(new MySQLSetVariableAdminExecutor((SetStatement) sqlStatement));
}
if (sqlStatement instanceof SelectStatement) {
if (isShowSpecialFunction((SelectStatement) sqlStatement, ShowConnectionIdExecutor.FUNCTION_NAME)) {
@@ -177,11 +168,6 @@ public final class MySQLAdminExecutorCreator implements DatabaseAdminExecutorCre
return ProxyContext.getInstance().getAllDatabaseNames().stream().anyMatch(each -> ProxyContext.getInstance().getDatabase(each).containsDataSource());
}
- private boolean isSetClientEncoding(final SetStatement setStatement) {
- Iterator<VariableAssignSegment> iterator = setStatement.getVariableAssigns().iterator();
- return iterator.hasNext() && "charset".equalsIgnoreCase(iterator.next().getVariable().getVariable());
- }
-
@Override
public String getType() {
return "MySQL";
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSessionVariableHandler.java
similarity index 60%
copy from shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java
copy to shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSessionVariableHandler.java
index 847ac040492..edfcb182370 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSessionVariableHandler.java
@@ -15,27 +15,14 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor;
+package org.apache.shardingsphere.proxy.backend.text.admin.mysql;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
-import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutor;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatement;
-
-import java.sql.SQLException;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.SessionVariableHandler;
+import org.apache.shardingsphere.spi.annotation.SingletonSPI;
/**
- * No Resource set executor.
+ * Session variable handler for MySQL.
*/
-@Getter
-@RequiredArgsConstructor
-public final class NoResourceSetExecutor implements DatabaseAdminExecutor {
-
- private final SetStatement sqlStatement;
-
- @Override
- public void execute(final ConnectionSession connectionSession) throws SQLException {
- return;
- }
+@SingletonSPI
+public interface MySQLSessionVariableHandler extends SessionVariableHandler {
}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSessionVariableHandlerFactory.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSessionVariableHandlerFactory.java
new file mode 100644
index 00000000000..dadcdc0a80c
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSessionVariableHandlerFactory.java
@@ -0,0 +1,48 @@
+/*
+ * 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.text.admin.mysql;
+
+import org.apache.shardingsphere.spi.ShardingSphereServiceLoader;
+import org.apache.shardingsphere.spi.type.typed.TypedSPIRegistry;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Factory for {@link MySQLSessionVariableHandler}.
+ */
+public final class MySQLSessionVariableHandlerFactory {
+
+ static {
+ ShardingSphereServiceLoader.register(MySQLSessionVariableHandler.class);
+ }
+
+ /**
+ * Get list of {@link MySQLSessionVariableHandler} for variables.
+ *
+ * @param variableNames variable names
+ * @return {@link MySQLSessionVariableHandler} for variables
+ */
+ public static List<MySQLSessionVariableHandler> getHandlers(final List<String> variableNames) {
+ List<MySQLSessionVariableHandler> result = new ArrayList<>(variableNames.size());
+ for (String each : variableNames) {
+ result.add(TypedSPIRegistry.findRegisteredService(MySQLSessionVariableHandler.class, each).orElseGet(DefaultMySQLSessionVariableHandler::new));
+ }
+ return result;
+ }
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSetVariableAdminExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSetVariableAdminExecutor.java
new file mode 100644
index 00000000000..f290bbc2cf6
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSetVariableAdminExecutor.java
@@ -0,0 +1,92 @@
+/*
+ * 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.text.admin.mysql;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.infra.binder.SQLStatementContextFactory;
+import org.apache.shardingsphere.infra.binder.statement.SQLStatementContext;
+import org.apache.shardingsphere.infra.database.type.DatabaseTypeFactory;
+import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
+import org.apache.shardingsphere.parser.rule.SQLParserRule;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
+import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutor;
+import org.apache.shardingsphere.proxy.backend.text.data.DatabaseBackendHandler;
+import org.apache.shardingsphere.proxy.backend.text.data.impl.SchemaAssignedDatabaseBackendHandler;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dal.VariableAssignSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.SQLStatement;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatement;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Set variable admin executor for MySQL.
+ */
+@RequiredArgsConstructor
+public final class MySQLSetVariableAdminExecutor implements DatabaseAdminExecutor {
+
+ private final SetStatement setStatement;
+
+ @Override
+ public void execute(final ConnectionSession connectionSession) throws SQLException {
+ Map<String, String> sessionVariables = extractSessionVariables();
+ List<MySQLSessionVariableHandler> handlers = MySQLSessionVariableHandlerFactory.getHandlers(new ArrayList<>(sessionVariables.keySet()));
+ for (MySQLSessionVariableHandler each : handlers) {
+ each.handle(connectionSession, setStatement);
+ }
+ executeSetGlobalVariablesIfPresent(connectionSession);
+ }
+
+ private Map<String, String> extractSessionVariables() {
+ return setStatement.getVariableAssigns().stream().filter(each -> !"global".equalsIgnoreCase(each.getVariable().getScope()))
+ .collect(Collectors.toMap(each -> each.getVariable().getVariable(), VariableAssignSegment::getAssignValue));
+ }
+
+ private Map<String, String> extractGlobalVariables() {
+ return setStatement.getVariableAssigns().stream().filter(each -> "global".equalsIgnoreCase(each.getVariable().getScope()))
+ .collect(Collectors.toMap(each -> each.getVariable().getVariable(), VariableAssignSegment::getAssignValue, (oldValue, newValue) -> newValue, LinkedHashMap::new));
+ }
+
+ private void executeSetGlobalVariablesIfPresent(final ConnectionSession connectionSession) throws SQLException {
+ if (null == connectionSession.getDatabaseName()) {
+ return;
+ }
+ String concatenatedGlobalVariables = extractGlobalVariables().entrySet().stream().map(entry -> String.format("@@GLOBAL.%s = %s", entry.getKey(), entry.getValue()))
+ .collect(Collectors.joining(", "));
+ if (concatenatedGlobalVariables.isEmpty()) {
+ return;
+ }
+ String sql = "SET " + concatenatedGlobalVariables;
+ MetaDataContexts metaDataContexts = ProxyContext.getInstance().getContextManager().getMetaDataContexts();
+ SQLParserRule sqlParserRule = metaDataContexts.getMetaData().getGlobalRuleMetaData().getSingleRule(SQLParserRule.class);
+ SQLStatement sqlStatement = sqlParserRule.getSQLParserEngine(DatabaseTypeFactory.getInstance("MySQL").getType()).parse(sql, false);
+ SQLStatementContext<?> sqlStatementContext = SQLStatementContextFactory.newInstance(ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getDatabases(),
+ sqlStatement, connectionSession.getDefaultDatabaseName());
+ DatabaseBackendHandler databaseBackendHandler = new SchemaAssignedDatabaseBackendHandler(sqlStatementContext, sql, connectionSession);
+ try {
+ databaseBackendHandler.execute();
+ } finally {
+ databaseBackendHandler.close();
+ }
+ }
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/MySQLSetCharsetExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/MySQLSetCharsetExecutor.java
index 9144cd4fd4e..f48a08076f7 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/MySQLSetCharsetExecutor.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/MySQLSetCharsetExecutor.java
@@ -17,35 +17,47 @@
package org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor;
-import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.db.protocol.CommonConstants;
import org.apache.shardingsphere.db.protocol.mysql.constant.MySQLServerInfo;
import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
-import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutor;
+import org.apache.shardingsphere.proxy.backend.text.admin.mysql.MySQLSessionVariableHandler;
import org.apache.shardingsphere.sql.parser.sql.common.segment.dal.VariableAssignSegment;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatement;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
-import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.Locale;
+import java.util.Set;
+import java.util.TreeSet;
/**
* Set charset executor of MySQL.
*/
-@RequiredArgsConstructor
-public final class MySQLSetCharsetExecutor implements DatabaseAdminExecutor {
+public final class MySQLSetCharsetExecutor implements MySQLSessionVariableHandler {
- private final SetStatement setStatement;
+ private static final Set<String> TYPE_ALIASES = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+
+ private static final Set<String> CHARSET_VARIABLE_NAMES = new HashSet<>(Arrays.asList("charset", "character_set_client"));
+
+ static {
+ TYPE_ALIASES.add("character_set_client");
+ }
@Override
- public void execute(final ConnectionSession connectionSession) throws SQLException {
- VariableAssignSegment segment = setStatement.getVariableAssigns().iterator().next();
- String value = formatValue(segment.getAssignValue().trim());
+ public void handle(final ConnectionSession connectionSession, final SetStatement setStatement) {
+ String value = formatValue(getCharacterSetValue(setStatement));
connectionSession.getAttributeMap().attr(CommonConstants.CHARSET_ATTRIBUTE_KEY).set(parseCharset(value));
}
+ private String getCharacterSetValue(final SetStatement setStatement) {
+ return setStatement.getVariableAssigns().stream().filter(each -> CHARSET_VARIABLE_NAMES.contains(each.getVariable().getVariable().toLowerCase(Locale.ROOT)))
+ .map(VariableAssignSegment::getAssignValue).findFirst().orElse("");
+ }
+
private String formatValue(final String value) {
return value.startsWith("'") && value.endsWith("'") || value.startsWith("\"") && value.endsWith("\"") ? value.substring(1, value.length() - 1) : value.trim();
}
@@ -66,4 +78,14 @@ public final class MySQLSetCharsetExecutor implements DatabaseAdminExecutor {
}
}
}
+
+ @Override
+ public String getType() {
+ return "charset";
+ }
+
+ @Override
+ public Collection<String> getTypeAliases() {
+ return TYPE_ALIASES;
+ }
}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/data/DatabaseBackendHandlerFactory.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/data/DatabaseBackendHandlerFactory.java
index 5e4348f8469..c00436ec3e8 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/data/DatabaseBackendHandlerFactory.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/data/DatabaseBackendHandlerFactory.java
@@ -52,7 +52,6 @@ public final class DatabaseBackendHandlerFactory {
return new UnicastDatabaseBackendHandler(sqlStatementContext, sql, connectionSession);
}
if (sqlStatement instanceof SetStatement && null == connectionSession.getDatabaseName()) {
- // TODO Handle SET GLOBAL and SET SESSION differently
return new DatabaseBackendHandler() {
@Override
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.mysql.MySQLSessionVariableHandler b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.mysql.MySQLSessionVariableHandler
new file mode 100644
index 00000000000..be3c5ce6224
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.mysql.MySQLSessionVariableHandler
@@ -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.text.admin.mysql.executor.MySQLSetCharsetExecutor
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/TextProtocolBackendHandlerFactoryTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/TextProtocolBackendHandlerFactoryTest.java
index d2a11166c9d..c8cae084581 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/TextProtocolBackendHandlerFactoryTest.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/TextProtocolBackendHandlerFactoryTest.java
@@ -32,7 +32,6 @@ import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
import org.apache.shardingsphere.proxy.backend.text.admin.DatabaseAdminQueryBackendHandler;
import org.apache.shardingsphere.proxy.backend.text.admin.DatabaseAdminUpdateBackendHandler;
-import org.apache.shardingsphere.proxy.backend.text.data.DatabaseBackendHandler;
import org.apache.shardingsphere.proxy.backend.text.data.impl.SchemaAssignedDatabaseBackendHandler;
import org.apache.shardingsphere.proxy.backend.text.data.impl.UnicastDatabaseBackendHandler;
import org.apache.shardingsphere.proxy.backend.text.distsql.ral.QueryableRALBackendHandler;
@@ -185,17 +184,6 @@ public final class TextProtocolBackendHandlerFactoryTest extends ProxyContextRes
@Test
public void assertNewInstanceWithSet() throws SQLException {
- String sql = "set @num=1";
- ProxyContext proxyContext = ProxyContext.getInstance();
- when(proxyContext.getAllDatabaseNames()).thenReturn(new HashSet<>(Collections.singletonList("schema")));
- when(proxyContext.getContextManager().getMetaDataContexts().getMetaData().getDatabases().containsKey("schema")).thenReturn(true);
- when(proxyContext.getDatabase("schema").containsDataSource()).thenReturn(true);
- TextProtocolBackendHandler actual = TextProtocolBackendHandlerFactory.newInstance(databaseType, sql, Optional::empty, connectionSession);
- assertThat(actual, instanceOf(DatabaseBackendHandler.class));
- }
-
- @Test
- public void assertNewInstanceWithSetNoResource() throws SQLException {
String sql = "set @num=1";
TextProtocolBackendHandler actual = TextProtocolBackendHandlerFactory.newInstance(databaseType, sql, Optional::empty, connectionSession);
assertThat(actual, instanceOf(DatabaseAdminUpdateBackendHandler.class));
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSessionVariableHandlerFactoryTest.java
similarity index 56%
copy from shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java
copy to shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSessionVariableHandlerFactoryTest.java
index 847ac040492..20683955878 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSessionVariableHandlerFactoryTest.java
@@ -15,27 +15,24 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor;
+package org.apache.shardingsphere.proxy.backend.text.admin.mysql;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
-import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutor;
-import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatement;
+import org.junit.Test;
-import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.List;
-/**
- * No Resource set executor.
- */
-@Getter
-@RequiredArgsConstructor
-public final class NoResourceSetExecutor implements DatabaseAdminExecutor {
-
- private final SetStatement sqlStatement;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+public final class MySQLSessionVariableHandlerFactoryTest {
- @Override
- public void execute(final ConnectionSession connectionSession) throws SQLException {
- return;
+ @Test
+ public void assertGetHandlers() {
+ List<MySQLSessionVariableHandler> actual = MySQLSessionVariableHandlerFactory.getHandlers(Arrays.asList("test_fixture", "test_fixture"));
+ assertThat(actual.size(), is(2));
+ assertThat(actual.get(0), instanceOf(TestFixtureSessionVariableHandler.class));
+ assertThat(actual.get(1), instanceOf(TestFixtureSessionVariableHandler.class));
}
}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSetVariableAdminExecutorTest.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSetVariableAdminExecutorTest.java
new file mode 100644
index 00000000000..db7da356a9a
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/MySQLSetVariableAdminExecutorTest.java
@@ -0,0 +1,80 @@
+/*
+ * 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.text.admin.mysql;
+
+import org.apache.shardingsphere.infra.metadata.database.rule.ShardingSphereRuleMetaData;
+import org.apache.shardingsphere.mode.manager.ContextManager;
+import org.apache.shardingsphere.parser.config.SQLParserRuleConfiguration;
+import org.apache.shardingsphere.parser.rule.SQLParserRule;
+import org.apache.shardingsphere.proxy.backend.context.ProxyContext;
+import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
+import org.apache.shardingsphere.proxy.backend.text.data.impl.SchemaAssignedDatabaseBackendHandler;
+import org.apache.shardingsphere.proxy.backend.util.ProxyContextRestorer;
+import org.apache.shardingsphere.sql.parser.api.CacheOption;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dal.VariableAssignSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dal.VariableSegment;
+import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatement;
+import org.apache.shardingsphere.sql.parser.sql.dialect.statement.mysql.dal.MySQLSetStatement;
+import org.junit.Test;
+import org.mockito.MockedConstruction;
+
+import java.sql.SQLException;
+import java.util.Collections;
+
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public final class MySQLSetVariableAdminExecutorTest extends ProxyContextRestorer {
+
+ @Test
+ public void assertExecute() throws SQLException {
+ SetStatement setStatement = prepareSetStatement();
+ MySQLSetVariableAdminExecutor executor = new MySQLSetVariableAdminExecutor(setStatement);
+ ConnectionSession connectionSession = mock(ConnectionSession.class);
+ when(connectionSession.getDatabaseName()).thenReturn("db");
+ ProxyContext.init(mock(ContextManager.class, RETURNS_DEEP_STUBS));
+ when(ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getGlobalRuleMetaData())
+ .thenReturn(new ShardingSphereRuleMetaData(Collections.singletonList(new SQLParserRule(new SQLParserRuleConfiguration(false, new CacheOption(1, 1), new CacheOption(1, 1))))));
+ try (MockedConstruction<SchemaAssignedDatabaseBackendHandler> mockConstruction = mockConstruction(SchemaAssignedDatabaseBackendHandler.class)) {
+ executor.execute(connectionSession);
+ verify(mockConstruction.constructed().get(0)).execute();
+ }
+ verify(connectionSession).setCurrentDatabase("'value'");
+ }
+
+ private SetStatement prepareSetStatement() {
+ VariableAssignSegment setGlobalMaxConnectionAssignSegment = new VariableAssignSegment();
+ VariableSegment maxConnectionVariableSegment = new VariableSegment();
+ maxConnectionVariableSegment.setScope("global");
+ maxConnectionVariableSegment.setVariable("max_connections");
+ setGlobalMaxConnectionAssignSegment.setVariable(maxConnectionVariableSegment);
+ setGlobalMaxConnectionAssignSegment.setAssignValue("151");
+ VariableAssignSegment setTestFixtureAssignSegment = new VariableAssignSegment();
+ VariableSegment testFixtureSegment = new VariableSegment();
+ testFixtureSegment.setVariable("test_fixture");
+ setTestFixtureAssignSegment.setVariable(testFixtureSegment);
+ setTestFixtureAssignSegment.setAssignValue("'value'");
+ SetStatement result = new MySQLSetStatement();
+ result.getVariableAssigns().add(setGlobalMaxConnectionAssignSegment);
+ result.getVariableAssigns().add(setTestFixtureAssignSegment);
+ return result;
+ }
+}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/TestFixtureSessionVariableHandler.java
similarity index 62%
rename from shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java
rename to shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/TestFixtureSessionVariableHandler.java
index 847ac040492..9930c89863f 100644
--- a/shardingsphere-proxy/shardingsphere-proxy-backend/src/main/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/executor/NoResourceSetExecutor.java
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/java/org/apache/shardingsphere/proxy/backend/text/admin/mysql/TestFixtureSessionVariableHandler.java
@@ -15,27 +15,22 @@
* limitations under the License.
*/
-package org.apache.shardingsphere.proxy.backend.text.admin.mysql.executor;
+package org.apache.shardingsphere.proxy.backend.text.admin.mysql;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.proxy.backend.session.ConnectionSession;
-import org.apache.shardingsphere.proxy.backend.text.admin.executor.DatabaseAdminExecutor;
+import org.apache.shardingsphere.sql.parser.sql.common.segment.dal.VariableAssignSegment;
import org.apache.shardingsphere.sql.parser.sql.common.statement.dal.SetStatement;
-import java.sql.SQLException;
-
-/**
- * No Resource set executor.
- */
-@Getter
-@RequiredArgsConstructor
-public final class NoResourceSetExecutor implements DatabaseAdminExecutor {
+public final class TestFixtureSessionVariableHandler implements MySQLSessionVariableHandler {
- private final SetStatement sqlStatement;
+ @Override
+ public void handle(final ConnectionSession connectionSession, final SetStatement setStatement) {
+ connectionSession.setCurrentDatabase(setStatement.getVariableAssigns().stream()
+ .filter(each -> getType().equals(each.getVariable().getVariable())).map(VariableAssignSegment::getAssignValue).findFirst().orElseThrow(IllegalArgumentException::new));
+ }
@Override
- public void execute(final ConnectionSession connectionSession) throws SQLException {
- return;
+ public String getType() {
+ return "test_fixture";
}
}
diff --git a/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.mysql.MySQLSessionVariableHandler b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.mysql.MySQLSessionVariableHandler
new file mode 100644
index 00000000000..b3b01dbfcd1
--- /dev/null
+++ b/shardingsphere-proxy/shardingsphere-proxy-backend/src/test/resources/META-INF/services/org.apache.shardingsphere.proxy.backend.text.admin.mysql.MySQLSessionVariableHandler
@@ -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.text.admin.mysql.TestFixtureSessionVariableHandler