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 2026/08/14 12:51:31 UTC
(shardingsphere) branch master updated: Refactor MySQL COM_QUERY binary literal handling (#39461)
This is an automated email from the ASF dual-hosted git repository.
terrymanu 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 4b8adc732ef Refactor MySQL COM_QUERY binary literal handling (#39461)
4b8adc732ef is described below
commit 4b8adc732ef10c3509fa9e8d9f5792b201e3a2fb
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Fri Aug 14 20:51:24 2026 +0800
Refactor MySQL COM_QUERY binary literal handling (#39461)
---
.../query/MySQLComQueryBackendHandlerFactory.java | 53 +++++++++++++---------
.../MySQLComQueryBackendHandlerFactoryTest.java | 9 +++-
2 files changed, 38 insertions(+), 24 deletions(-)
diff --git a/proxy/frontend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryBackendHandlerFactory.java b/proxy/frontend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryBackendHandlerFactory.java
index 7137afa51c7..e7af928a454 100644
--- a/proxy/frontend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryBackendHandlerFactory.java
+++ b/proxy/frontend/dialect/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryBackendHandlerFactory.java
@@ -46,6 +46,8 @@ import org.apache.shardingsphere.sql.parser.statement.core.statement.type.dml.Up
import org.apache.shardingsphere.sql.parser.statement.core.util.MultiSQLSplitter;
import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
import java.util.Optional;
/**
@@ -61,18 +63,27 @@ final class MySQLComQueryBackendHandlerFactory {
static ProxyBackendHandler newInstance(final MySQLComQueryPacket packet, final ConnectionSession connectionSession) throws SQLException {
DatabaseType databaseType = TypedSPILoader.getService(DatabaseType.class, "MySQL");
String sql = packet.getSQL();
- Optional<ProxyBackendHandler> binaryLiteralHandler = tryCreateBinaryLiteralHandler(databaseType, sql, packet, connectionSession);
- if (binaryLiteralHandler.isPresent()) {
- return binaryLiteralHandler.get();
+ List<Object> binaryLiteralValues = Collections.emptyList();
+ SQLStatement sqlStatement;
+ Optional<ExtractionResult> extractionResult = tryExtractBinaryLiteral(sql, packet, connectionSession);
+ if (extractionResult.isPresent() && 1 == MultiSQLSplitter.split(extractionResult.get().getSql()).size()) {
+ String parameterizedSQL = SQLHintUtils.removeHint(extractionResult.get().getSql());
+ try {
+ sqlStatement = ProxySQLComQueryParser.parse(parameterizedSQL, databaseType, connectionSession);
+ sql = parameterizedSQL;
+ binaryLiteralValues = extractionResult.get().getBinaryLiteralValues();
+ } catch (final DialectSQLParsingException ignored) {
+ sqlStatement = ProxySQLComQueryParser.parse(sql, databaseType, connectionSession);
+ }
+ } else {
+ sqlStatement = ProxySQLComQueryParser.parse(sql, databaseType, connectionSession);
}
- SQLStatement sqlStatement = ProxySQLComQueryParser.parse(sql, databaseType, connectionSession);
- return areMultiStatements(connectionSession, sqlStatement, sql)
+ return binaryLiteralValues.isEmpty() && areMultiStatements(connectionSession, sqlStatement, sql)
? new MySQLMultiStatementsProxyBackendHandler(connectionSession, sqlStatement, sql)
- : ProxyBackendHandlerFactory.newInstance(databaseType, sql, sqlStatement, connectionSession, packet.getHintValueContext());
+ : createSingleStatementHandler(databaseType, sql, sqlStatement, binaryLiteralValues, packet, connectionSession);
}
- private static Optional<ProxyBackendHandler> tryCreateBinaryLiteralHandler(final DatabaseType databaseType, final String sql, final MySQLComQueryPacket packet,
- final ConnectionSession connectionSession) throws SQLException {
+ private static Optional<ExtractionResult> tryExtractBinaryLiteral(final String sql, final MySQLComQueryPacket packet, final ConnectionSession connectionSession) throws SQLException {
Optional<byte[]> originalSQLBytes = packet.findOriginalSQLBytes();
if (!originalSQLBytes.isPresent() || !requiresBinaryLiteralInspection(sql)) {
return Optional.empty();
@@ -80,24 +91,22 @@ final class MySQLComQueryBackendHandlerFactory {
boolean noBackslashEscapes = MySQLSessionSQLMode.get(connectionSession.getAttributeMap()).isNoBackslashEscapes();
ExtractionResult extractionResult = MySQLComQueryBinaryParameterExtractor.extract(
originalSQLBytes.get(), connectionSession.getAttributeMap().attr(CommonConstants.CHARSET_ATTRIBUTE_KEY).get(), noBackslashEscapes);
- if (extractionResult.getBinaryLiteralValues().isEmpty() || 1 != MultiSQLSplitter.split(extractionResult.getSql()).size()) {
- return Optional.empty();
- }
- String parameterizedSQL = SQLHintUtils.removeHint(extractionResult.getSql());
- SQLStatement parameterizedSQLStatement;
- try {
- parameterizedSQLStatement = ProxySQLComQueryParser.parse(parameterizedSQL, databaseType, connectionSession);
- } catch (final DialectSQLParsingException ignored) {
- return Optional.empty();
+ return extractionResult.getBinaryLiteralValues().isEmpty() ? Optional.empty() : Optional.of(extractionResult);
+ }
+
+ private static ProxyBackendHandler createSingleStatementHandler(final DatabaseType databaseType, final String sql, final SQLStatement sqlStatement,
+ final List<Object> binaryLiteralValues, final MySQLComQueryPacket packet,
+ final ConnectionSession connectionSession) throws SQLException {
+ if (binaryLiteralValues.isEmpty()) {
+ return ProxyBackendHandlerFactory.newInstance(databaseType, sql, sqlStatement, connectionSession, packet.getHintValueContext());
}
ShardingSphereMetaData metaData = ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData();
- SQLStatementContext sqlStatementContext = new SQLBindEngine(metaData, connectionSession.getCurrentDatabaseName(), packet.getHintValueContext()).bind(parameterizedSQLStatement);
+ SQLStatementContext sqlStatementContext = new SQLBindEngine(metaData, connectionSession.getCurrentDatabaseName(), packet.getHintValueContext()).bind(sqlStatement);
if (sqlStatementContext instanceof ParameterAware) {
- ((ParameterAware) sqlStatementContext).bindParameters(extractionResult.getBinaryLiteralValues());
+ ((ParameterAware) sqlStatementContext).bindParameters(binaryLiteralValues);
}
- QueryContext queryContext = new QueryContext(
- sqlStatementContext, parameterizedSQL, extractionResult.getBinaryLiteralValues(), packet.getHintValueContext(), connectionSession.getConnectionContext(), metaData, true);
- return Optional.of(ProxyBackendHandlerFactory.newInstance(databaseType, queryContext, connectionSession, true));
+ QueryContext queryContext = new QueryContext(sqlStatementContext, sql, binaryLiteralValues, packet.getHintValueContext(), connectionSession.getConnectionContext(), metaData, true);
+ return ProxyBackendHandlerFactory.newInstance(databaseType, queryContext, connectionSession, true);
}
private static boolean requiresBinaryLiteralInspection(final String sql) {
diff --git a/proxy/frontend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryBackendHandlerFactoryTest.java b/proxy/frontend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryBackendHandlerFactoryTest.java
index ca357aae047..dcbe22470da 100644
--- a/proxy/frontend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryBackendHandlerFactoryTest.java
+++ b/proxy/frontend/dialect/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/command/query/text/query/MySQLComQueryBackendHandlerFactoryTest.java
@@ -72,6 +72,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isA;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
@@ -163,6 +164,7 @@ class MySQLComQueryBackendHandlerFactoryTest {
QueryContext actual = queryContextCaptor.getValue();
assertThat(actual.getSql(), is("INSERT INTO t (id, v) VALUES (1, ?)"));
assertThat(actual.getParameters().size(), is(1));
+ assertTrue(actual.isUseCache());
Blob blob = (Blob) actual.getParameters().get(0);
assertArrayEquals(new byte[]{(byte) 0xFF}, blob.getBytes(1, (int) blob.length()));
}
@@ -207,11 +209,14 @@ class MySQLComQueryBackendHandlerFactoryTest {
@Test
void assertCreateStandardHandlerForStructuralBinaryLiteral() throws SQLException {
- when(packet.getSQL()).thenReturn("SHOW TABLES LIKE _binary'�'");
+ String sql = "SHOW TABLES LIKE _binary'�'";
+ when(packet.getSQL()).thenReturn(sql);
when(packet.findOriginalSQLBytes()).thenReturn(Optional.of(sql("SHOW TABLES LIKE _binary'", (byte) 0xFF, "'")));
when(connectionSession.getAttributeMap().attr(CommonConstants.CHARSET_ATTRIBUTE_KEY).get()).thenReturn(StandardCharsets.UTF_8);
+ ProxyBackendHandler expectedBackendHandler = mock(ProxyBackendHandler.class);
+ when(ProxyBackendHandlerFactory.newInstance(eq(databaseType), eq(sql), any(SQLStatement.class), eq(connectionSession), any())).thenReturn(expectedBackendHandler);
ProxyBackendHandler actual = MySQLComQueryBackendHandlerFactory.newInstance(packet, connectionSession);
- assertThat(actual, is(proxyBackendHandler));
+ assertThat(actual, is(expectedBackendHandler));
}
private static byte[] sql(final String prefix, final byte content, final String suffix) {