This is an automated email from the ASF dual-hosted git repository.

tuichenchuxin 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 cc6d5ebc025 Fix mysql client multi statements option in protocol 
(#29688)
cc6d5ebc025 is described below

commit cc6d5ebc025023ab3737bd18ea06add6959bf3ca
Author: ZhangCheng <[email protected]>
AuthorDate: Wed Jan 10 18:39:19 2024 +0800

    Fix mysql client multi statements option in protocol (#29688)
    
    * Fix mysql client multi statements option in protocol
    
    * Fix mysql client multi statements option in protocol
    
    * Fix mysql client multi statements option in protocol
    
    * Fix mysql client multi statements option in protocol
    
    * Fix mysql client multi statements option in protocol
    
    * Fix mysql client multi statements option in protocol
    
    * Fix mysql client multi statements option in protocol
    
    * fix
---
 .../mysql/constant/MySQLCapabilityFlag.java        |  2 +-
 .../handshake/MySQLHandshakeResponse41Packet.java  |  9 +++++++
 .../mysql/constant/MySQLCapabilityFlagTest.java    |  2 +-
 .../packet/handshake/MySQLHandshakePacketTest.java |  2 +-
 .../MySQLHandshakeResponse41PacketTest.java        | 19 ++++++++++++++
 .../authentication/MySQLAuthenticationEngine.java  |  7 +++++-
 .../MySQLAuthenticationEngineTest.java             |  2 ++
 .../e2e/env/runtime/DataSourceEnvironment.java     |  4 +--
 .../param/array/E2ETestParameterGenerator.java     |  7 ++++--
 .../cases/dml/dataset/db/delete_with_multiple.xml  | 29 ++++++++++++++++++++++
 .../resources/cases/dml/dml-integration-delete.xml |  6 +++++
 11 files changed, 81 insertions(+), 8 deletions(-)

diff --git 
a/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLCapabilityFlag.java
 
b/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLCapabilityFlag.java
index 6d5eda2f71b..7a1c18c82a8 100644
--- 
a/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLCapabilityFlag.java
+++ 
b/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLCapabilityFlag.java
@@ -97,7 +97,7 @@ public enum MySQLCapabilityFlag {
      * @return handshake capability flags upper bit
      */
     public static int calculateHandshakeCapabilityFlagsUpper() {
-        return calculateCapabilityFlags(CLIENT_PLUGIN_AUTH) >> 16;
+        return calculateCapabilityFlags(CLIENT_MULTI_STATEMENTS, 
CLIENT_PLUGIN_AUTH) >> 16;
     }
     
     /**
diff --git 
a/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakeResponse41Packet.java
 
b/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakeResponse41Packet.java
index 96c1f90bb4d..7d98bc1ee36 100644
--- 
a/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakeResponse41Packet.java
+++ 
b/db-protocol/mysql/src/main/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakeResponse41Packet.java
@@ -23,6 +23,7 @@ import lombok.Setter;
 import 
org.apache.shardingsphere.db.protocol.mysql.constant.MySQLAuthenticationMethod;
 import 
org.apache.shardingsphere.db.protocol.mysql.constant.MySQLCapabilityFlag;
 import org.apache.shardingsphere.db.protocol.mysql.packet.MySQLPacket;
+import 
org.apache.shardingsphere.db.protocol.mysql.packet.command.admin.MySQLComSetOptionPacket;
 import org.apache.shardingsphere.db.protocol.mysql.payload.MySQLPacketPayload;
 
 /**
@@ -49,8 +50,11 @@ public final class MySQLHandshakeResponse41Packet extends 
MySQLPacket {
     
     private String authPluginName;
     
+    private int multiStatementsOption;
+    
     public MySQLHandshakeResponse41Packet(final MySQLPacketPayload payload) {
         capabilityFlags = payload.readInt4();
+        multiStatementsOption = readMultiStatementsOption(capabilityFlags);
         maxPacketSize = payload.readInt4();
         characterSet = payload.readInt1();
         payload.skipReserved(23);
@@ -60,6 +64,11 @@ public final class MySQLHandshakeResponse41Packet extends 
MySQLPacket {
         authPluginName = readAuthPluginName(payload);
     }
     
+    private int readMultiStatementsOption(final int capabilityFlags) {
+        return 0 == (capabilityFlags & 
MySQLCapabilityFlag.CLIENT_MULTI_STATEMENTS.getValue()) ? 
MySQLComSetOptionPacket.MYSQL_OPTION_MULTI_STATEMENTS_OFF
+                : MySQLComSetOptionPacket.MYSQL_OPTION_MULTI_STATEMENTS_ON;
+    }
+    
     private byte[] readAuthResponse(final MySQLPacketPayload payload) {
         if (0 != (capabilityFlags & 
MySQLCapabilityFlag.CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA.getValue())) {
             return payload.readStringLenencByBytes();
diff --git 
a/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLCapabilityFlagTest.java
 
b/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLCapabilityFlagTest.java
index e89c0e9ae44..ebc3cb46e2c 100644
--- 
a/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLCapabilityFlagTest.java
+++ 
b/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/constant/MySQLCapabilityFlagTest.java
@@ -36,6 +36,6 @@ class MySQLCapabilityFlagTest {
     
     @Test
     void assertCalculateHandshakeCapabilityFlagsUpper() {
-        
assertThat(MySQLCapabilityFlag.calculateHandshakeCapabilityFlagsUpper(), 
is(0x0008));
+        
assertThat(MySQLCapabilityFlag.calculateHandshakeCapabilityFlagsUpper(), 
is(0x0009));
     }
 }
diff --git 
a/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakePacketTest.java
 
b/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakePacketTest.java
index ff25169d263..f4065216048 100644
--- 
a/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakePacketTest.java
+++ 
b/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakePacketTest.java
@@ -129,7 +129,7 @@ class MySQLHandshakePacketTest {
         
verify(payload).writeInt2(MySQLCapabilityFlag.calculateHandshakeCapabilityFlagsLower());
         verify(payload).writeInt1(MySQLConstants.DEFAULT_CHARSET.getId());
         
verify(payload).writeInt2(MySQLStatusFlag.SERVER_STATUS_AUTOCOMMIT.getValue());
-        
verify(payload).writeInt2(MySQLCapabilityFlag.CLIENT_PLUGIN_AUTH.getValue() >> 
16);
+        
verify(payload).writeInt2(MySQLCapabilityFlag.calculateHandshakeCapabilityFlagsUpper());
         
verify(payload).writeInt1(authPluginData.getAuthenticationPluginData().length + 
1);
         verify(payload).writeReserved(10);
         verify(payload).writeStringNul(new 
String(authPluginData.getAuthenticationPluginDataPart2()));
diff --git 
a/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakeResponse41PacketTest.java
 
b/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakeResponse41PacketTest.java
index 911071d588b..e0a5ad98ac2 100644
--- 
a/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakeResponse41PacketTest.java
+++ 
b/db-protocol/mysql/src/test/java/org/apache/shardingsphere/db/protocol/mysql/packet/handshake/MySQLHandshakeResponse41PacketTest.java
@@ -20,6 +20,7 @@ package 
org.apache.shardingsphere.db.protocol.mysql.packet.handshake;
 import 
org.apache.shardingsphere.db.protocol.mysql.constant.MySQLAuthenticationMethod;
 import 
org.apache.shardingsphere.db.protocol.mysql.constant.MySQLCapabilityFlag;
 import org.apache.shardingsphere.db.protocol.mysql.constant.MySQLConstants;
+import 
org.apache.shardingsphere.db.protocol.mysql.packet.command.admin.MySQLComSetOptionPacket;
 import org.apache.shardingsphere.db.protocol.mysql.payload.MySQLPacketPayload;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -55,6 +56,24 @@ class MySQLHandshakeResponse41PacketTest {
         verify(payload).skipReserved(23);
     }
     
+    @Test
+    void assertNewWithPayloadWithClientMultiStatements() {
+        
when(payload.readInt1()).thenReturn(MySQLConstants.DEFAULT_CHARSET.getId());
+        
when(payload.readInt4()).thenReturn(MySQLCapabilityFlag.CLIENT_MULTI_STATEMENTS.getValue(),
 1000);
+        when(payload.readStringNul()).thenReturn("root", "sharding_db");
+        when(payload.readStringNulByBytes()).thenReturn(new byte[]{1});
+        MySQLHandshakeResponse41Packet actual = new 
MySQLHandshakeResponse41Packet(payload);
+        assertThat(actual.getMultiStatementsOption(), 
is(MySQLComSetOptionPacket.MYSQL_OPTION_MULTI_STATEMENTS_ON));
+        assertThat(actual.getMaxPacketSize(), is(1000));
+        assertThat(actual.getCharacterSet(), 
is(MySQLConstants.DEFAULT_CHARSET.getId()));
+        assertThat(actual.getUsername(), is("root"));
+        assertThat(actual.getAuthResponse(), is(new byte[]{1}));
+        assertThat(actual.getCapabilityFlags(), 
is(MySQLCapabilityFlag.CLIENT_MULTI_STATEMENTS.getValue()));
+        assertNull(actual.getDatabase());
+        assertNull(actual.getAuthPluginName());
+        verify(payload).skipReserved(23);
+    }
+    
     @Test
     void assertNewWithPayloadWithAuthPluginName() {
         
when(payload.readInt1()).thenReturn(MySQLConstants.DEFAULT_CHARSET.getId());
diff --git 
a/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngine.java
 
b/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngine.java
index c62e37daaa2..31233a864ea 100644
--- 
a/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngine.java
+++ 
b/proxy/frontend/type/mysql/src/main/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngine.java
@@ -119,9 +119,10 @@ public final class MySQLAuthenticationEngine implements 
AuthenticationEngine {
             }
             throw new HandshakeException();
         }
-        String database = handshakeResponsePacket.getDatabase();
         authResponse = handshakeResponsePacket.getAuthResponse();
+        setMultiStatementsOption(context, handshakeResponsePacket);
         setCharacterSet(context, handshakeResponsePacket);
+        String database = handshakeResponsePacket.getDatabase();
         if (!Strings.isNullOrEmpty(database) && 
!ProxyContext.getInstance().databaseExists(database)) {
             throw new UnknownDatabaseException(database);
         }
@@ -137,6 +138,10 @@ public final class MySQLAuthenticationEngine implements 
AuthenticationEngine {
         return AuthenticationResultBuilder.finished(username, hostname, 
database);
     }
     
+    private void setMultiStatementsOption(final ChannelHandlerContext context, 
final MySQLHandshakeResponse41Packet handshakeResponsePacket) {
+        
context.channel().attr(MySQLConstants.MYSQL_OPTION_MULTI_STATEMENTS).set(handshakeResponsePacket.getMultiStatementsOption());
+    }
+    
     private void setCharacterSet(final ChannelHandlerContext context, final 
MySQLHandshakeResponse41Packet handshakeResponsePacket) {
         MySQLCharacterSet characterSet = 
MySQLCharacterSet.findById(handshakeResponsePacket.getCharacterSet());
         
context.channel().attr(CommonConstants.CHARSET_ATTRIBUTE_KEY).set(characterSet.getCharset());
diff --git 
a/proxy/frontend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngineTest.java
 
b/proxy/frontend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngineTest.java
index a922952f079..50148519ad6 100644
--- 
a/proxy/frontend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngineTest.java
+++ 
b/proxy/frontend/type/mysql/src/test/java/org/apache/shardingsphere/proxy/frontend/mysql/authentication/MySQLAuthenticationEngineTest.java
@@ -148,6 +148,7 @@ class MySQLAuthenticationEngineTest {
         when(channel.remoteAddress()).thenReturn(new 
InetSocketAddress("localhost", 3307));
         
when(channel.attr(CommonConstants.CHARSET_ATTRIBUTE_KEY)).thenReturn(mock(Attribute.class));
         
when(channel.attr(MySQLConstants.MYSQL_CHARACTER_SET_ATTRIBUTE_KEY)).thenReturn(mock(Attribute.class));
+        
when(channel.attr(MySQLConstants.MYSQL_OPTION_MULTI_STATEMENTS)).thenReturn(mock(Attribute.class));
         when(channelHandlerContext.channel()).thenReturn(channel);
         when(payload.readInt1()).thenReturn(1);
         
when(payload.readInt4()).thenReturn(MySQLCapabilityFlag.CLIENT_PLUGIN_AUTH.getValue());
@@ -321,6 +322,7 @@ class MySQLAuthenticationEngineTest {
         
when(result.attr(CommonConstants.CHARSET_ATTRIBUTE_KEY)).thenReturn(mock(Attribute.class));
         
when(result.attr(MySQLConstants.MYSQL_CHARACTER_SET_ATTRIBUTE_KEY)).thenReturn(mock(Attribute.class));
         
when(result.attr(MySQLConstants.MYSQL_SEQUENCE_ID)).thenReturn(mock(Attribute.class));
+        
when(result.attr(MySQLConstants.MYSQL_OPTION_MULTI_STATEMENTS)).thenReturn(mock(Attribute.class));
         return result;
     }
     
diff --git 
a/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/runtime/DataSourceEnvironment.java
 
b/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/runtime/DataSourceEnvironment.java
index c715bfc5cc7..ca114712809 100644
--- 
a/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/runtime/DataSourceEnvironment.java
+++ 
b/test/e2e/env/src/test/java/org/apache/shardingsphere/test/e2e/env/runtime/DataSourceEnvironment.java
@@ -61,7 +61,7 @@ public final class DataSourceEnvironment {
                 return 
"jdbc:h2:mem:test_db;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MySQL;USER=root;PASSWORD=Root@123";
             case "MySQL":
                 return 
String.format("jdbc:mysql://%s:%s?useSSL=true&requireSSL=true&enabledTLSProtocols=TLSv1.2,TLSv1.3&verifyServerCertificate=false"
-                        + 
"&useServerPrepStmts=true&useLocalSessionState=true&characterEncoding=utf-8", 
host, port);
+                        + 
"&useServerPrepStmts=true&useLocalSessionState=true&characterEncoding=utf-8&allowMultiQueries=true",
 host, port);
             case "PostgreSQL":
                 return 
String.format("jdbc:postgresql://%s:%s/?ssl=on&sslmode=prefer", host, port);
             case "openGauss":
@@ -88,7 +88,7 @@ public final class DataSourceEnvironment {
             case "MySQL":
                 return String.format(
                         
"jdbc:mysql://%s:%s/%s?useSSL=true&requireSSL=true&enabledTLSProtocols=TLSv1.2,TLSv1.3&verifyServerCertificate=false"
-                                + 
"&useServerPrepStmts=true&useLocalSessionState=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true",
+                                + 
"&useServerPrepStmts=true&useLocalSessionState=true&characterEncoding=utf-8&allowPublicKeyRetrieval=true&allowMultiQueries=true",
                         host, port, dataSourceName);
             case "PostgreSQL":
                 return 
String.format("jdbc:postgresql://%s:%s/%s?ssl=on&sslmode=prefer", host, port, 
dataSourceName);
diff --git 
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/framework/param/array/E2ETestParameterGenerator.java
 
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/framework/param/array/E2ETestParameterGenerator.java
index af2fe6a5f75..1145720542a 100644
--- 
a/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/framework/param/array/E2ETestParameterGenerator.java
+++ 
b/test/e2e/sql/src/test/java/org/apache/shardingsphere/test/e2e/framework/param/array/E2ETestParameterGenerator.java
@@ -163,14 +163,17 @@ public final class E2ETestParameterGenerator {
     
     private Collection<E2ETestParameter> getCaseTestParameter(final 
IntegrationTestCaseContext testCaseContext, final DatabaseType databaseType, 
final SQLCommandType sqlCommandType) {
         Collection<E2ETestParameter> result = new LinkedList<>();
-        for (String adapter : envAdapters) {
-            result.addAll(getCaseTestParameter(testCaseContext, adapter, 
databaseType, sqlCommandType));
+        for (String each : envAdapters) {
+            result.addAll(getCaseTestParameter(testCaseContext, each, 
databaseType, sqlCommandType));
         }
         return result;
     }
     
     private Collection<E2ETestParameter> getCaseTestParameter(final 
IntegrationTestCaseContext testCaseContext, final String adapter,
                                                               final 
DatabaseType databaseType, final SQLCommandType sqlCommandType) {
+        if (null != testCaseContext.getTestCase().getAdapters() && 
!testCaseContext.getTestCase().getAdapters().contains(adapter)) {
+            return Collections.emptyList();
+        }
         Collection<String> scenarios = null == 
testCaseContext.getTestCase().getScenarioTypes() ? Collections.emptyList() : 
Arrays.asList(testCaseContext.getTestCase().getScenarioTypes().split(","));
         return envScenarios.stream().filter(each -> scenarios.isEmpty() || 
scenarios.contains(each))
                 .map(each -> new CaseTestParameter(testCaseContext, adapter, 
each, envMode, databaseType, sqlCommandType)).collect(Collectors.toList());
diff --git 
a/test/e2e/sql/src/test/resources/cases/dml/dataset/db/delete_with_multiple.xml 
b/test/e2e/sql/src/test/resources/cases/dml/dataset/db/delete_with_multiple.xml
new file mode 100644
index 00000000000..c36bff07b07
--- /dev/null
+++ 
b/test/e2e/sql/src/test/resources/cases/dml/dataset/db/delete_with_multiple.xml
@@ -0,0 +1,29 @@
+<!--
+  ~ 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.
+  -->
+
+<dataset update-count="38">
+    <metadata data-nodes="db_${0..9}.t_order">
+        <column name="order_id" type="numeric" />
+        <column name="user_id" type="numeric" />
+        <column name="status" type="varchar" />
+        <column name="merchant_id" type="numeric" />
+        <column name="remark" type="varchar" />
+        <column name="creation_date" type="datetime" />
+    </metadata>
+    <row data-node="db_9.t_order" values="2900, 29, init, 19, test, 
2017-08-08" />
+    <row data-node="db_9.t_order" values="2901, 29, init, 20, test, 
2017-08-08" />
+</dataset>
diff --git 
a/test/e2e/sql/src/test/resources/cases/dml/dml-integration-delete.xml 
b/test/e2e/sql/src/test/resources/cases/dml/dml-integration-delete.xml
index 937057bb0af..b6f6bcc76c4 100644
--- a/test/e2e/sql/src/test/resources/cases/dml/dml-integration-delete.xml
+++ b/test/e2e/sql/src/test/resources/cases/dml/dml-integration-delete.xml
@@ -66,4 +66,10 @@
     <test-case sql="DELETE FROM t_shadow WHERE user_id = ? and order_id in (?, 
?)" db-types="PostgreSQL" 
scenario-types="shadow,sharding_encrypt_shadow,encrypt_shadow,readwrite_splitting_and_shadow,sharding_and_shadow">
         <assertion parameters="0:int, 4:int, 5:int" 
expected-data-file="shadow_delete_order_by_user_id.xml" />
     </test-case>
+    
+    <test-case
+            sql="DELETE FROM t_order WHERE order_id = 1000 AND user_id = 
10;DELETE FROM t_order WHERE order_id = 1001 AND user_id = 11;DELETE FROM 
t_order WHERE user_id &lt; 29;" db-types="MySQL"
+            scenario-types="db" sql-case-types="LITERAL" adapters="proxy">
+        <assertion expected-data-file="delete_with_multiple.xml" />
+    </test-case>
 </integration-test-cases>

Reply via email to