This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new 1a8590e0b22 branch-4.0: [fix](protocol) Support CLIENT_DEPRECATE_EOF
to fix empty result with MySQL driver 9.5.0 #61050 (#61062)
1a8590e0b22 is described below
commit 1a8590e0b227ee9a43430244215394e99201d7af
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Mar 6 13:18:11 2026 +0800
branch-4.0: [fix](protocol) Support CLIENT_DEPRECATE_EOF to fix empty
result with MySQL driver 9.5.0 #61050 (#61062)
Cherry-picked from #61050
Co-authored-by: Mingyu Chen (Rayner) <[email protected]>
---
.../org/apache/doris/mysql/MysqlCapability.java | 7 +-
.../java/org/apache/doris/mysql/MysqlOkPacket.java | 9 +-
.../doris/mysql/MysqlResultSetEndPacket.java | 61 +++++++++++
.../java/org/apache/doris/qe/ConnectProcessor.java | 19 +++-
.../java/org/apache/doris/qe/FEOpExecutor.java | 4 +
.../java/org/apache/doris/qe/StmtExecutor.java | 49 +++++----
.../apache/doris/mysql/MysqlCapabilityTest.java | 3 +-
.../org/apache/doris/mysql/MysqlOkPacketTest.java | 23 +++-
.../doris/mysql/MysqlResultSetEndPacketTest.java | 120 +++++++++++++++++++++
gensrc/thrift/FrontendService.thrift | 2 +
10 files changed, 266 insertions(+), 31 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlCapability.java
b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlCapability.java
index cbfa88038be..d58f046eb53 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlCapability.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlCapability.java
@@ -74,13 +74,14 @@ public class MysqlCapability {
private static final int DEFAULT_FLAGS =
Flag.CLIENT_PROTOCOL_41.getFlagBit()
| Flag.CLIENT_CONNECT_WITH_DB.getFlagBit() |
Flag.CLIENT_SECURE_CONNECTION.getFlagBit()
- | Flag.CLIENT_PLUGIN_AUTH.getFlagBit() |
Flag.CLIENT_LOCAL_FILES.getFlagBit() | Flag.CLIENT_LONG_FLAG
- .getFlagBit();
+ | Flag.CLIENT_PLUGIN_AUTH.getFlagBit() |
Flag.CLIENT_LOCAL_FILES.getFlagBit()
+ | Flag.CLIENT_LONG_FLAG.getFlagBit() |
Flag.CLIENT_DEPRECATE_EOF.getFlagBit();
private static final int SSL_FLAGS = Flag.CLIENT_PROTOCOL_41.getFlagBit()
| Flag.CLIENT_CONNECT_WITH_DB.getFlagBit() |
Flag.CLIENT_SECURE_CONNECTION.getFlagBit()
| Flag.CLIENT_PLUGIN_AUTH.getFlagBit() |
Flag.CLIENT_LOCAL_FILES.getFlagBit()
- | Flag.CLIENT_LONG_FLAG.getFlagBit() |
Flag.CLIENT_SSL.getFlagBit();
+ | Flag.CLIENT_LONG_FLAG.getFlagBit() | Flag.CLIENT_SSL.getFlagBit()
+ | Flag.CLIENT_DEPRECATE_EOF.getFlagBit();
public static final MysqlCapability DEFAULT_CAPABILITY = new
MysqlCapability(DEFAULT_FLAGS);
public static final MysqlCapability SSL_CAPABILITY = new
MysqlCapability(SSL_FLAGS);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlOkPacket.java
b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlOkPacket.java
index 778dfd8c3c4..4fa80102317 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlOkPacket.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlOkPacket.java
@@ -59,8 +59,13 @@ public class MysqlOkPacket extends MysqlPacket {
// if ((STATUS_FLAGS &
MysqlStatusFlag.SERVER_SESSION_STATE_CHANGED) != 0) {
// }
} else {
- if (!Strings.isNullOrEmpty(infoMessage)) {
- // NOTE: in datasheet, use EOF string, but in the code, mysql
use length encoded string
+ // Always write the info field as a length-encoded string.
+ // When CLIENT_DEPRECATE_EOF is negotiated, the driver's
OkPacket.parse()
+ // unconditionally reads STRING_LENENC for info, so an empty
string must
+ // still be written (as a single 0x00 byte representing length 0).
+ if (Strings.isNullOrEmpty(infoMessage)) {
+ serializer.writeVInt(0);
+ } else {
serializer.writeLenEncodedString(infoMessage);
}
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlResultSetEndPacket.java
b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlResultSetEndPacket.java
new file mode 100644
index 00000000000..5543b85c361
--- /dev/null
+++
b/fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlResultSetEndPacket.java
@@ -0,0 +1,61 @@
+// 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.doris.mysql;
+
+import org.apache.doris.qe.QueryState;
+
+/**
+ * MySQL OK packet with 0xFE header, used as the end-of-result-set marker
+ * when CLIENT_DEPRECATE_EOF is set.
+ *
+ * When CLIENT_DEPRECATE_EOF capability is negotiated, the traditional EOF
packet (0xFE, ≤5 bytes)
+ * is replaced by an OK packet that also uses 0xFE as its header byte but has
a payload larger
+ * than 5 bytes. This is called a "ResultSet OK" packet in the MySQL protocol
documentation.
+ *
+ * See:
https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_ok_packet.html
+ */
+public class MysqlResultSetEndPacket extends MysqlPacket {
+ // 0xFE header to distinguish from regular OK (0x00)
+ private static final int RESULTSET_OK_INDICATOR = 0xFE;
+ private static final long AFFECTED_ROWS = 0;
+ private static final long LAST_INSERT_ID = 0;
+
+ private int serverStatus = 0;
+ private int warningCount = 0;
+
+ public MysqlResultSetEndPacket(QueryState state) {
+ this.serverStatus = state.serverStatus;
+ }
+
+ @Override
+ public void writeTo(MysqlSerializer serializer) {
+ // header: 0xFE (same as EOF, but the payload length > 5 distinguishes
it)
+ serializer.writeInt1(RESULTSET_OK_INDICATOR);
+ // affected_rows: int<lenenc>
+ serializer.writeVInt(AFFECTED_ROWS);
+ // last_insert_id: int<lenenc>
+ serializer.writeVInt(LAST_INSERT_ID);
+ // status_flags: int<2>
+ serializer.writeInt2(serverStatus);
+ // warnings: int<2>
+ serializer.writeInt2(warningCount);
+ // info: string<lenenc> (empty string, written as a single 0x00 byte
for length 0)
+ // The driver's OkPacket.parse() unconditionally reads this field.
+ serializer.writeVInt(0);
+ }
+}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java
index 99527e99f2c..4811f911f17 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/ConnectProcessor.java
@@ -44,6 +44,7 @@ import org.apache.doris.metric.MetricRepo;
import org.apache.doris.mysql.MysqlChannel;
import org.apache.doris.mysql.MysqlCommand;
import org.apache.doris.mysql.MysqlPacket;
+import org.apache.doris.mysql.MysqlResultSetEndPacket;
import org.apache.doris.mysql.MysqlSerializer;
import org.apache.doris.mysql.MysqlServerStatusFlag;
import org.apache.doris.nereids.SqlCacheContext;
@@ -557,7 +558,17 @@ public abstract class ConnectProcessor {
// only Mysql protocol
protected ByteBuffer getResultPacket() {
Preconditions.checkState(connectType.equals(ConnectType.MYSQL));
- MysqlPacket packet = ctx.getState().toResponsePacket();
+ MysqlPacket packet;
+ // When CLIENT_DEPRECATE_EOF is set and the state is EOF (end of
result set),
+ // we need to send a "ResultSet OK" packet (0xFE header with payload >
5 bytes)
+ // instead of the traditional EOF packet. This is required by the
MySQL protocol
+ // and expected by MySQL Connector/J 9.5.0+.
+ if (ctx.getState().getStateType() == QueryState.MysqlStateType.EOF
+ && ctx.getMysqlChannel().clientDeprecatedEOF()) {
+ packet = new MysqlResultSetEndPacket(ctx.getState());
+ } else {
+ packet = ctx.getState().toResponsePacket();
+ }
if (packet == null) {
// possible two cases:
// 1. handler has send request
@@ -647,6 +658,12 @@ public abstract class ConnectProcessor {
// set compute group
ctx.setComputeGroup(Env.getCurrentEnv().getAuth().getComputeGroup(ctx.getQualifiedUser()));
+ // Propagate the client's CLIENT_DEPRECATE_EOF capability to the proxy
channel.
+ // This ensures the master generates packets matching the original
client's protocol.
+ if (request.isSetClientDeprecatedEOF() &&
request.isClientDeprecatedEOF()) {
+ ctx.getMysqlChannel().setClientDeprecatedEOF();
+ }
+
ctx.setThreadLocalInfo();
StmtExecutor executor = null;
try {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/FEOpExecutor.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/FEOpExecutor.java
index 9dcd379f913..6a461cb5c94 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/FEOpExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/FEOpExecutor.java
@@ -206,6 +206,10 @@ public class FEOpExecutor {
}
}
+ // Propagate the client's CLIENT_DEPRECATE_EOF capability so the
master FE
+ // generates packets matching the original client's protocol
expectations.
+
params.setClientDeprecatedEOF(ctx.getMysqlChannel().clientDeprecatedEOF());
+
return params;
}
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
index 2c8d095c45f..3a7f4976dce 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java
@@ -67,7 +67,6 @@ import org.apache.doris.mysql.FieldInfo;
import org.apache.doris.mysql.MysqlChannel;
import org.apache.doris.mysql.MysqlCommand;
import org.apache.doris.mysql.MysqlEofPacket;
-import org.apache.doris.mysql.MysqlOkPacket;
import org.apache.doris.mysql.MysqlSerializer;
import org.apache.doris.mysql.ProxyMysqlChannel;
import org.apache.doris.nereids.NereidsPlanner;
@@ -1538,11 +1537,15 @@ public class StmtExecutor {
}
context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
}
- // send EOF
- serializer.reset();
- MysqlEofPacket eofPacket = new MysqlEofPacket(context.getState());
- eofPacket.writeTo(serializer);
- context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
+ // When CLIENT_DEPRECATE_EOF is set, the server should not send the
intermediate
+ // EOF packet after column definitions. The client will go directly
from column
+ // definitions to reading data rows.
+ if (!context.getMysqlChannel().clientDeprecatedEOF()) {
+ serializer.reset();
+ MysqlEofPacket eofPacket = new MysqlEofPacket(context.getState());
+ eofPacket.writeTo(serializer);
+ context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
+ }
}
private List<PrimitiveType> exprToStringType(List<Expr> exprs) {
@@ -1584,15 +1587,15 @@ public class StmtExecutor {
serializer.writeField(colNames.get(i), Type.STRING);
context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
}
- serializer.reset();
+ // When CLIENT_DEPRECATE_EOF is set, no EOF/OK packet should be
sent after
+ // parameter definitions. The driver knows how many params to
expect from the
+ // prepare OK packet and simply stops reading after that count.
if (!context.getMysqlChannel().clientDeprecatedEOF()) {
+ serializer.reset();
MysqlEofPacket eofPacket = new
MysqlEofPacket(context.getState());
eofPacket.writeTo(serializer);
- } else {
- MysqlOkPacket okPacket = new MysqlOkPacket(context.getState());
- okPacket.writeTo(serializer);
+
context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
}
- context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
}
if (numColumns > 0) {
for (Slot slot : output) {
@@ -1611,15 +1614,15 @@ public class StmtExecutor {
}
context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
}
- serializer.reset();
+ // When CLIENT_DEPRECATE_EOF is set, no EOF/OK packet should be
sent after
+ // column definitions. The driver knows how many columns to expect
from the
+ // prepare OK packet and simply stops reading after that count.
if (!context.getMysqlChannel().clientDeprecatedEOF()) {
+ serializer.reset();
MysqlEofPacket eofPacket = new
MysqlEofPacket(context.getState());
eofPacket.writeTo(serializer);
- } else {
- MysqlOkPacket okPacket = new MysqlOkPacket(context.getState());
- okPacket.writeTo(serializer);
+
context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
}
- context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
}
context.getMysqlChannel().flush();
context.getState().setNoop();
@@ -1668,11 +1671,15 @@ public class StmtExecutor {
context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
}
}
- // send EOF
- serializer.reset();
- MysqlEofPacket eofPacket = new MysqlEofPacket(context.getState());
- eofPacket.writeTo(serializer);
- context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
+ // When CLIENT_DEPRECATE_EOF is set, the server should not send the
intermediate
+ // EOF packet after column definitions. The client will go directly
from column
+ // definitions to reading data rows.
+ if (!context.getMysqlChannel().clientDeprecatedEOF()) {
+ serializer.reset();
+ MysqlEofPacket eofPacket = new MysqlEofPacket(context.getState());
+ eofPacket.writeTo(serializer);
+ context.getMysqlChannel().sendOnePacket(serializer.toByteBuffer());
+ }
}
public void sendResultSet(ResultSet resultSet) throws IOException {
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlCapabilityTest.java
b/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlCapabilityTest.java
index f3b4385b960..78197804b63 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlCapabilityTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlCapabilityTest.java
@@ -44,8 +44,9 @@ public class MysqlCapabilityTest {
public void testDefaultFlags() {
MysqlCapability capability = MysqlCapability.DEFAULT_CAPABILITY;
Assert.assertEquals("CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
CLIENT_LOCAL_FILES | CLIENT_PROTOCOL_41"
- + " | CLIENT_SECURE_CONNECTION | CLIENT_PLUGIN_AUTH",
+ + " | CLIENT_SECURE_CONNECTION | CLIENT_PLUGIN_AUTH |
CLIENT_DEPRECATE_EOF",
capability.toString());
Assert.assertTrue(capability.supportClientLocalFile());
+ Assert.assertTrue(capability.isDeprecatedEOF());
}
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlOkPacketTest.java
b/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlOkPacketTest.java
index 6cb157ee252..9fe47adbf5e 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlOkPacketTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlOkPacketTest.java
@@ -56,10 +56,27 @@ public class MysqlOkPacketTest {
// assert warnings, int2: 0
Assert.assertEquals(0x00, MysqlProto.readInt2(buffer));
- // assert info, eof string: "OK"
- // Assert.assertEquals("OK", new
String(MysqlProto.readEofString(buffer)));
-
+ // When infoMessage is empty, an empty len-encoded string (0x00)
should still be written.
+ // This is required because OkPacket.parse() in MySQL Connector/J
unconditionally reads
+ // STRING_LENENC for info. Without this byte, the driver throws
+ // ArrayIndexOutOfBoundsException when CLIENT_DEPRECATE_EOF is
negotiated.
+ Assert.assertEquals(0x00, MysqlProto.readVInt(buffer));
Assert.assertEquals(0, buffer.remaining());
}
+ @Test
+ public void testWritePayloadSizeGreaterThan5() {
+ // When CLIENT_DEPRECATE_EOF is negotiated, the driver distinguishes
between
+ // EOF packets (payload <= 5) and ResultSet OK packets (payload > 5).
+ // MysqlOkPacket payload must be > 5 to avoid being misidentified as
EOF.
+ // Payload: 0x00(1) + affected_rows(1) + last_insert_id(1) + status(2)
+ warnings(2) + info_len(1) = 8
+ MysqlOkPacket packet = new MysqlOkPacket(new QueryState());
+ MysqlSerializer serializer = MysqlSerializer.newInstance(capability);
+ packet.writeTo(serializer);
+
+ ByteBuffer buffer = serializer.toByteBuffer();
+ int payloadLength = buffer.remaining();
+ Assert.assertTrue("OK packet payload should be > 5 for
CLIENT_DEPRECATE_EOF compatibility, got: "
+ + payloadLength, payloadLength > 5);
+ }
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlResultSetEndPacketTest.java
b/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlResultSetEndPacketTest.java
new file mode 100644
index 00000000000..8dc0d18877f
--- /dev/null
+++
b/fe/fe-core/src/test/java/org/apache/doris/mysql/MysqlResultSetEndPacketTest.java
@@ -0,0 +1,120 @@
+// 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.doris.mysql;
+
+import org.apache.doris.qe.QueryState;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+
+public class MysqlResultSetEndPacketTest {
+ private MysqlCapability capability;
+
+ @Before
+ public void setUp() {
+ capability = new
MysqlCapability(MysqlCapability.Flag.CLIENT_PROTOCOL_41.getFlagBit());
+ }
+
+ @Test
+ public void testWriteHeader() {
+ // The ResultSet OK packet must start with 0xFE (same as EOF)
+ MysqlResultSetEndPacket packet = new MysqlResultSetEndPacket(new
QueryState());
+ MysqlSerializer serializer = MysqlSerializer.newInstance(capability);
+ packet.writeTo(serializer);
+
+ ByteBuffer buffer = serializer.toByteBuffer();
+
+ // assert header: 0xFE
+ Assert.assertEquals(0xFE, MysqlProto.readInt1(buffer));
+ }
+
+ @Test
+ public void testWriteFields() {
+ // Verify all fields are written correctly
+ MysqlResultSetEndPacket packet = new MysqlResultSetEndPacket(new
QueryState());
+ MysqlSerializer serializer = MysqlSerializer.newInstance(capability);
+ packet.writeTo(serializer);
+
+ ByteBuffer buffer = serializer.toByteBuffer();
+
+ // header: 0xFE
+ Assert.assertEquals(0xFE, MysqlProto.readInt1(buffer));
+
+ // affected_rows: int<lenenc> = 0
+ Assert.assertEquals(0, MysqlProto.readVInt(buffer));
+
+ // last_insert_id: int<lenenc> = 0
+ Assert.assertEquals(0, MysqlProto.readVInt(buffer));
+
+ // status_flags: int<2> = 0
+ Assert.assertEquals(0, MysqlProto.readInt2(buffer));
+
+ // warnings: int<2> = 0
+ Assert.assertEquals(0, MysqlProto.readInt2(buffer));
+
+ // info: string<lenenc> (empty, length = 0)
+ Assert.assertEquals(0, MysqlProto.readVInt(buffer));
+
+ // no remaining bytes
+ Assert.assertEquals(0, buffer.remaining());
+ }
+
+ @Test
+ public void testPayloadSizeGreaterThan5() {
+ // When CLIENT_DEPRECATE_EOF is negotiated, the MySQL driver uses
isResultSetOKPacket()
+ // to detect end-of-result-set. This method requires:
+ // (byteBuffer[0] & 0xff) == 0xFE && payloadLength > 5
+ // The traditional EOF packet has payloadLength == 5, so the ResultSet
OK packet
+ // MUST have payloadLength > 5 to be correctly identified.
+ MysqlResultSetEndPacket packet = new MysqlResultSetEndPacket(new
QueryState());
+ MysqlSerializer serializer = MysqlSerializer.newInstance(capability);
+ packet.writeTo(serializer);
+
+ ByteBuffer buffer = serializer.toByteBuffer();
+ int payloadLength = buffer.remaining();
+
+ // Payload: 0xFE(1) + affected_rows(1) + last_insert_id(1) + status(2)
+ warnings(2) + info(1) = 8
+ Assert.assertTrue("ResultSet OK packet payload must be > 5 for
isResultSetOKPacket(), got: "
+ + payloadLength, payloadLength > 5);
+ }
+
+ @Test
+ public void testDiffersFromEofPacket() {
+ // A traditional EOF packet has exactly 5 bytes payload.
+ // The ResultSet OK packet must have > 5 bytes to be distinguishable.
+ MysqlEofPacket eofPacket = new MysqlEofPacket(new QueryState());
+ MysqlSerializer eofSerializer =
MysqlSerializer.newInstance(capability);
+ eofPacket.writeTo(eofSerializer);
+ int eofPayloadLength = eofSerializer.toByteBuffer().remaining();
+
+ MysqlResultSetEndPacket rsEndPacket = new MysqlResultSetEndPacket(new
QueryState());
+ MysqlSerializer rsEndSerializer =
MysqlSerializer.newInstance(capability);
+ rsEndPacket.writeTo(rsEndSerializer);
+ int rsEndPayloadLength = rsEndSerializer.toByteBuffer().remaining();
+
+ // EOF payload should be <= 5
+ Assert.assertTrue("EOF packet payload should be <= 5, got: " +
eofPayloadLength,
+ eofPayloadLength <= 5);
+ // ResultSet OK payload should be > 5
+ Assert.assertTrue("ResultSet OK packet payload should be > 5, got: " +
rsEndPayloadLength,
+ rsEndPayloadLength > 5);
+ }
+}
diff --git a/gensrc/thrift/FrontendService.thrift
b/gensrc/thrift/FrontendService.thrift
index 3eb10c8de5f..fed7476a9c0 100644
--- a/gensrc/thrift/FrontendService.thrift
+++ b/gensrc/thrift/FrontendService.thrift
@@ -400,6 +400,8 @@ struct TMasterOpRequest {
// temporary table
1002: optional string sessionId
+ // propagate client's CLIENT_DEPRECATE_EOF capability for proxy forwarding
+ 1003: optional bool clientDeprecatedEOF
}
struct TColumnDefinition {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]