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 8597726a5e8 mysql-proxy: skip admin for no-FROM multi-expression 
selects; add tests (#37391)
8597726a5e8 is described below

commit 8597726a5e82b8d14f6c398f5f21348188dc180c
Author: Quanye Yang <[email protected]>
AuthorDate: Tue Dec 16 12:41:44 2025 +0800

    mysql-proxy: skip admin for no-FROM multi-expression selects; add tests 
(#37391)
---
 ...MySQLSelectWithoutFromAdminExecutorFactory.java |  8 ++++
 .../admin/MySQLAdminExecutorCreatorTest.java       | 45 ++++++++++++++++++++++
 2 files changed, 53 insertions(+)

diff --git 
a/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/factory/withoutfrom/MySQLSelectWithoutFromAdminExecutorFactory.java
 
b/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/factory/withoutfrom/MySQLSelectWithoutFromAdminExecutorFactory.java
index 470c536a131..c544e89bee7 100644
--- 
a/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/factory/withoutfrom/MySQLSelectWithoutFromAdminExecutorFactory.java
+++ 
b/proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/factory/withoutfrom/MySQLSelectWithoutFromAdminExecutorFactory.java
@@ -93,9 +93,17 @@ public final class 
MySQLSelectWithoutFromAdminExecutorFactory {
             return Optional.of(new NoResourceShowExecutor(sqlStatement));
         }
         boolean isUseDatabase = null != databaseName || 
sqlStatement.getFrom().isPresent();
+        if (!isUseDatabase && hasMultipleProjections(sqlStatement)) {
+            return Optional.empty();
+        }
         return isUseDatabase ? Optional.empty() : Optional.of(new 
UnicastResourceShowExecutor(sqlStatement, sql));
     }
     
+    private static boolean hasMultipleProjections(final SelectStatement 
sqlStatement) {
+        Collection<ProjectionSegment> projections = 
sqlStatement.getProjections().getProjections();
+        return projections.size() > 1;
+    }
+    
     private static boolean isEmptyResource(final ShardingSphereMetaData 
metaData) {
         Collection<ShardingSphereDatabase> databases = 
metaData.getAllDatabases();
         return databases.isEmpty() || 
databases.stream().noneMatch(ShardingSphereDatabase::containsDataSource);
diff --git 
a/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreatorTest.java
 
b/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreatorTest.java
index 3a4b72859bc..7f69967391c 100644
--- 
a/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreatorTest.java
+++ 
b/proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreatorTest.java
@@ -73,6 +73,7 @@ import 
org.apache.shardingsphere.test.infra.framework.extension.mock.StaticMockS
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Optional;
@@ -405,4 +406,48 @@ class MySQLAdminExecutorCreatorTest {
         Optional<DatabaseAdminExecutor> actual = new 
MySQLAdminExecutorCreator().create(sqlStatementContext, "DELETE FROM t", "", 
Collections.emptyList());
         assertThat(actual, is(Optional.empty()));
     }
+    
+    @Test
+    void assertCreateWithNoFromAndMultiProjectionsSkipsAdmin() {
+        ResourceMetaData resourceMetaData = new 
ResourceMetaData(Collections.singletonMap("ds_0", new MockedDataSource()));
+        ShardingSphereDatabase database = new ShardingSphereDatabase("db_0", 
databaseType, resourceMetaData, mock(RuleMetaData.class), 
Collections.emptyList());
+        initProxyContext(Collections.singleton(database));
+        
+        SelectStatement selectStatement = mock(SelectStatement.class);
+        when(selectStatement.getFrom()).thenReturn(Optional.empty());
+        ProjectionsSegment projectionsSegment = mock(ProjectionsSegment.class);
+        when(projectionsSegment.getProjections()).thenReturn(Arrays.asList(
+                new ExpressionProjectionSegment(0, 10, "database()"),
+                new ExpressionProjectionSegment(0, 10, "schema()"),
+                new ExpressionProjectionSegment(0, 10, 
"left(user(),instr(concat(user(),'@'),'@')-1)")));
+        when(selectStatement.getProjections()).thenReturn(projectionsSegment);
+        SelectStatementContext sqlStatementContext = 
mock(SelectStatementContext.class);
+        
when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
+        
+        Optional<DatabaseAdminExecutor> actual =
+                new MySQLAdminExecutorCreator().create(sqlStatementContext, 
"SELECT database(),schema(),left(user(),instr(concat(user(),'@'),'@')-1)", 
null, Collections.emptyList());
+        assertThat(actual, is(Optional.empty()));
+    }
+    
+    @Test
+    void assertCreateWithMultiSystemVariablesUseSysVarExecutor() {
+        initProxyContext(Collections.emptyList());
+        SelectStatement selectStatement = mock(SelectStatement.class);
+        when(selectStatement.getFrom()).thenReturn(Optional.empty());
+        ProjectionsSegment projectionsSegment = mock(ProjectionsSegment.class);
+        VariableSegment v1 = new VariableSegment(0, 0, "version", "SESSION");
+        VariableSegment v2 = new VariableSegment(0, 0, 
"transaction_isolation", "SESSION");
+        when(projectionsSegment.getProjections()).thenReturn(Arrays.asList(
+                new ExpressionProjectionSegment(0, 10, "@@session.version", 
v1),
+                new ExpressionProjectionSegment(0, 10, 
"@@session.transaction_isolation", v2)));
+        when(selectStatement.getProjections()).thenReturn(projectionsSegment);
+        
+        SelectStatementContext sqlStatementContext = 
mock(SelectStatementContext.class);
+        
when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
+        
+        Optional<DatabaseAdminExecutor> actual = new 
MySQLAdminExecutorCreator().create(
+                sqlStatementContext, "SELECT @@session.version, 
@@session.transaction_isolation", null, Collections.emptyList());
+        assertTrue(actual.isPresent());
+        assertThat(actual.get(), isA(MySQLSystemVariableQueryExecutor.class));
+    }
 }

Reply via email to