github-actions[bot] commented on code in PR #67520:
URL: https://github.com/apache/doris/pull/67520#discussion_r3930709964
##########
fe/fe-core/src/main/java/org/apache/doris/qe/FEOpExecutor.java:
##########
@@ -214,6 +214,7 @@ protected TMasterOpRequest buildStmtForwardParams() throws
AnalysisException {
if (null != ctx.getPrepareExecuteBuffer()) {
params.setPrepareExecuteBuffer(ctx.getPrepareExecuteBuffer());
}
+ params.setCursorFetchRequested(ctx.isCursorFetchRequested());
Review Comment:
[P1] Preserve binary execute mode without parameters
For a zero-placeholder prepared SELECT, `handleExecute` never sets
`prepareExecuteBuffer`, so this forwards `cursor_fetch_requested=true` without
any marker that makes the master take its prepared-execute branch.
`proxyExecute` then leaves the fresh context as `COM_SLEEP`; both coordinator
paths set `mysql_row_binary_format=false`, and non-empty rows are serialized as
text even though Connector/J is reading a COM_STMT_EXECUTE binary result. The
new regression uses `getServerPrepareJdbcUrl`, which connects directly to the
master, so it misses this path. Please forward execute/binary-result intent
independently of parameter bytes (or always carry an empty execute buffer) and
cover a follower-to-master non-empty result.
##########
fe/fe-core/src/main/java/org/apache/doris/qe/StmtExecutor.java:
##########
@@ -1987,17 +1983,37 @@ private void sendFields(List<String> colNames,
List<FieldInfo> fieldInfos, List<
channel.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.
+ sendMetadataTerminatorIfNeeded(channel);
+ }
+
+ private void sendMetadataTerminatorIfNeeded(MysqlChannel channel) throws
IOException {
if (!channel.clientDeprecatedEOF()) {
serializer.reset();
- MysqlEofPacket eofPacket = new MysqlEofPacket(context.getState());
- eofPacket.writeTo(serializer);
+ new MysqlEofPacket(context.getState()).writeTo(serializer);
+ channel.sendOnePacket(serializer.toByteBuffer());
+ } else if (connectorJConsumesCursorMetadataTerminator()) {
+ // Connector/J before 9.5 consumes the first OK packet after
column definitions
+ // while probing whether a requested cursor was created. Doris
does not create a
+ // cursor, so an empty result would otherwise lose its only end
marker and block.
+ serializer.reset();
+ new
MysqlResultSetEndPacket(context.getState()).writeTo(serializer);
channel.sendOnePacket(serializer.toByteBuffer());
}
}
+ private boolean connectorJConsumesCursorMetadataTerminator() {
+ if (!context.isCursorFetchRequested()) {
+ return false;
+ }
+ Map<String, String> connectAttributes = context.getConnectAttributes();
+ if (!MYSQL_CONNECTOR_J.equals(connectAttributes.get("_client_name"))) {
Review Comment:
[P1] Cover the legacy Connector/J cursor consumers
Connector/J 5.1.49 and 6.0.6 have the same cursor-probe behavior this
workaround targets: when Doris advertises `CLIENT_DEPRECATE_EOF`, they consume
the packet after column definitions for a cursor request. Those releases send
`_client_name=MySQL Connector Java` (and 5.x/6.x versions), so this predicate
never inserts the compatibility terminator. An empty result therefore still
consumes its only final OK and waits for another packet; a non-empty result can
consume its first binary row as status. Please include the verified legacy
identity/version families (or classify by the affected protocol behavior) and
add a boundary test.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]