Skip to content

Commit 3c212dd

Browse files
committed
Work around server query attributes bug. Fixes #1106
MySQL Server versions 8.0.23-8.0.25 contain bugs that prevent them from parsing attributes in the COM_STMT_EXECUTE packet. The new PARAMETER_COUNT_AVAILABLE flag is added in 8.0.26 to enable attributes to be sent. If we detect an older server (that advertises support for query attributes), we send an empty string parameter name, but omit the attributes.
1 parent 91a4111 commit 3c212dd

File tree

2 files changed

+13
-9
lines changed

2 files changed

+13
-9
lines changed

src/MySqlConnector/Core/SingleCommandPayloadCreator.cs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,25 +82,29 @@ private static void WritePreparedStatement(IMySqlCommand command, PreparedStatem
8282

8383
var attributes = command.RawAttributes;
8484
var supportsQueryAttributes = command.Connection!.Session.SupportsQueryAttributes;
85-
8685
writer.Write(preparedStatement.StatementId);
8786

8887
// NOTE: documentation is not updated yet, but due to bugs in MySQL Server 8.0.23-8.0.25, the PARAMETER_COUNT_AVAILABLE (0x08)
89-
// flag has to be set in the 'flags' block in order for query attributes to be sent with a prepared statement; we do not version-sniff the
90-
// server but assume that it must support this flag
91-
writer.Write((byte) (supportsQueryAttributes ? 8 : 0));
88+
// flag has to be set in the 'flags' block in order for query attributes to be sent with a prepared statement.
89+
var sendQueryAttributes = supportsQueryAttributes && command.Connection.Session.ServerVersion.Version is not { Major: 8, Minor: 0, Build: >= 23 and <= 25 };
90+
writer.Write((byte) (sendQueryAttributes ? 8 : 0));
9291
writer.Write(1);
9392

9493
var commandParameterCount = preparedStatement.Statement.ParameterNames?.Count ?? 0;
9594
var attributeCount = attributes?.Count ?? 0;
96-
if (supportsQueryAttributes)
95+
if (sendQueryAttributes)
9796
{
9897
writer.WriteLengthEncodedInteger((uint) (commandParameterCount + attributeCount));
9998
}
100-
else if (attributeCount > 0)
99+
else
101100
{
102-
Log.Warn("Session{0} has attributes for CommandId {1} but the server does not support them", command.Connection!.Session.Id, preparedStatement.StatementId);
103-
attributeCount = 0;
101+
if (supportsQueryAttributes && commandParameterCount > 0)
102+
writer.WriteLengthEncodedInteger((uint) commandParameterCount);
103+
if (attributeCount > 0)
104+
{
105+
Log.Warn("Session{0} has attributes for CommandId {1} but the server does not support them", command.Connection!.Session.Id, preparedStatement.StatementId);
106+
attributeCount = 0;
107+
}
104108
}
105109

106110
if (commandParameterCount > 0 || attributeCount > 0)

tests/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ with Connector/NET and that [known bugs have been fixed](https://mysqlconnector.
77

88
The tests require a MySQL server. The simplest way to run one is with [Docker](https://www.docker.com/community-edition):
99

10-
docker run -d --rm --name mysqlconnector -e MYSQL_ROOT_PASSWORD=pass -p 3306:3306 mysql:8.0.23 --max-allowed-packet=96M --character-set-server=utf8mb4 --log-bin-trust-function-creators=1 --local-infile=1 --max-connections=250
10+
docker run -d --rm --name mysqlconnector -e MYSQL_ROOT_PASSWORD=pass -p 3306:3306 mysql:8.0.27 --max-allowed-packet=96M --character-set-server=utf8mb4 --log-bin-trust-function-creators=1 --local-infile=1 --max-connections=250
1111

1212
Copy the file `SideBySide/config.json.example` to `SideBySide/config.json`, then edit
1313
the `config.json` file in order to connect to your server. If you are using the Docker

0 commit comments

Comments
 (0)