Skip to content

Commit 7a5bae5

Browse files
mysql-proxy: skip admin for no-FROM multi-expression selects; add tests
1 parent cbd13f8 commit 7a5bae5

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

proxy/backend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/factory/withoutfrom/MySQLSelectWithoutFromAdminExecutorFactory.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,17 @@ private static Optional<DatabaseAdminExecutor> mockExecutor(final SelectStatemen
9393
return Optional.of(new NoResourceShowExecutor(sqlStatement));
9494
}
9595
boolean isUseDatabase = null != databaseName || sqlStatement.getFrom().isPresent();
96+
if (!isUseDatabase && hasMultipleProjections(sqlStatement)) {
97+
return Optional.empty();
98+
}
9699
return isUseDatabase ? Optional.empty() : Optional.of(new UnicastResourceShowExecutor(sqlStatement, sql));
97100
}
98101

102+
private static boolean hasMultipleProjections(final SelectStatement sqlStatement) {
103+
Collection<ProjectionSegment> projections = sqlStatement.getProjections().getProjections();
104+
return projections.size() > 1;
105+
}
106+
99107
private static boolean isEmptyResource(final ShardingSphereMetaData metaData) {
100108
Collection<ShardingSphereDatabase> databases = metaData.getAllDatabases();
101109
return databases.isEmpty() || databases.stream().noneMatch(ShardingSphereDatabase::containsDataSource);

proxy/backend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/backend/mysql/handler/admin/MySQLAdminExecutorCreatorTest.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import org.junit.jupiter.api.Test;
7474
import org.junit.jupiter.api.extension.ExtendWith;
7575

76+
import java.util.Arrays;
7677
import java.util.Collection;
7778
import java.util.Collections;
7879
import java.util.Optional;
@@ -405,4 +406,48 @@ void assertCreateWithDMLStatement() {
405406
Optional<DatabaseAdminExecutor> actual = new MySQLAdminExecutorCreator().create(sqlStatementContext, "DELETE FROM t", "", Collections.emptyList());
406407
assertThat(actual, is(Optional.empty()));
407408
}
409+
410+
@Test
411+
void assertCreateWithNoFromAndMultiProjectionsSkipsAdmin() {
412+
ResourceMetaData resourceMetaData = new ResourceMetaData(Collections.singletonMap("ds_0", new MockedDataSource()));
413+
ShardingSphereDatabase database = new ShardingSphereDatabase("db_0", databaseType, resourceMetaData, mock(RuleMetaData.class), Collections.emptyList());
414+
initProxyContext(Collections.singleton(database));
415+
416+
SelectStatement selectStatement = mock(SelectStatement.class);
417+
when(selectStatement.getFrom()).thenReturn(Optional.empty());
418+
ProjectionsSegment projectionsSegment = mock(ProjectionsSegment.class);
419+
when(projectionsSegment.getProjections()).thenReturn(Arrays.asList(
420+
new ExpressionProjectionSegment(0, 10, "database()"),
421+
new ExpressionProjectionSegment(0, 10, "schema()"),
422+
new ExpressionProjectionSegment(0, 10, "left(user(),instr(concat(user(),'@'),'@')-1)")));
423+
when(selectStatement.getProjections()).thenReturn(projectionsSegment);
424+
SelectStatementContext sqlStatementContext = mock(SelectStatementContext.class);
425+
when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
426+
427+
Optional<DatabaseAdminExecutor> actual =
428+
new MySQLAdminExecutorCreator().create(sqlStatementContext, "SELECT database(),schema(),left(user(),instr(concat(user(),'@'),'@')-1)", null, Collections.emptyList());
429+
assertThat(actual, is(Optional.empty()));
430+
}
431+
432+
@Test
433+
void assertCreateWithMultiSystemVariablesUseSysVarExecutor() {
434+
initProxyContext(Collections.emptyList());
435+
SelectStatement selectStatement = mock(SelectStatement.class);
436+
when(selectStatement.getFrom()).thenReturn(Optional.empty());
437+
ProjectionsSegment projectionsSegment = mock(ProjectionsSegment.class);
438+
VariableSegment v1 = new VariableSegment(0, 0, "version", "SESSION");
439+
VariableSegment v2 = new VariableSegment(0, 0, "transaction_isolation", "SESSION");
440+
when(projectionsSegment.getProjections()).thenReturn(Arrays.asList(
441+
new ExpressionProjectionSegment(0, 10, "@@session.version", v1),
442+
new ExpressionProjectionSegment(0, 10, "@@session.transaction_isolation", v2)));
443+
when(selectStatement.getProjections()).thenReturn(projectionsSegment);
444+
445+
SelectStatementContext sqlStatementContext = mock(SelectStatementContext.class);
446+
when(sqlStatementContext.getSqlStatement()).thenReturn(selectStatement);
447+
448+
Optional<DatabaseAdminExecutor> actual = new MySQLAdminExecutorCreator().create(
449+
sqlStatementContext, "SELECT @@session.version, @@session.transaction_isolation", null, Collections.emptyList());
450+
assertTrue(actual.isPresent());
451+
assertThat(actual.get(), isA(MySQLSystemVariableQueryExecutor.class));
452+
}
408453
}

0 commit comments

Comments
 (0)