Skip to content

Commit b2c0d5a

Browse files
committed
Implement CLIENT_DEPRECATE_EOF. Fixes #322
1 parent 48f1b95 commit b2c0d5a

File tree

5 files changed

+47
-13
lines changed

5 files changed

+47
-13
lines changed

src/MySqlConnector/MySqlClient/Results/ResultSet.cs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,11 @@ public async Task<ResultSet> ReadResultSetHeaderAsync(IOBehavior ioBehavior)
9292
ColumnDefinitions[column] = ColumnDefinitionPayload.Create(payload);
9393
}
9494

95-
payload = await Session.ReceiveReplyAsync(ioBehavior, CancellationToken.None).ConfigureAwait(false);
96-
EofPayload.Create(payload);
95+
if (!Session.SupportsDeprecateEof)
96+
{
97+
payload = await Session.ReceiveReplyAsync(ioBehavior, CancellationToken.None).ConfigureAwait(false);
98+
EofPayload.Create(payload);
99+
}
97100

98101
LastInsertId = -1;
99102
State = ResultSetState.ReadResultSetHeader;
@@ -192,12 +195,22 @@ async Task<Row> ScanRowAsyncAwaited(Task<PayloadData> payloadTask, CancellationT
192195

193196
Row ScanRowAsyncRemainder(PayloadData payload)
194197
{
195-
if (EofPayload.IsEof(payload))
198+
if (payload.HeaderByte == EofPayload.Signature)
196199
{
197-
var eof = EofPayload.Create(payload);
198-
BufferState = (eof.ServerStatus & ServerStatus.MoreResultsExist) == 0 ? ResultSetState.NoMoreData : ResultSetState.HasMoreData;
199-
m_rowBuffered = null;
200-
return null;
200+
if (Session.SupportsDeprecateEof && OkPayload.IsOk(payload, Session.SupportsDeprecateEof))
201+
{
202+
var ok = OkPayload.Create(payload, Session.SupportsDeprecateEof);
203+
BufferState = (ok.ServerStatus & ServerStatus.MoreResultsExist) == 0 ? ResultSetState.NoMoreData : ResultSetState.HasMoreData;
204+
m_rowBuffered = null;
205+
return null;
206+
}
207+
if (!Session.SupportsDeprecateEof && EofPayload.IsEof(payload))
208+
{
209+
var eof = EofPayload.Create(payload);
210+
BufferState = (eof.ServerStatus & ServerStatus.MoreResultsExist) == 0 ? ResultSetState.NoMoreData : ResultSetState.HasMoreData;
211+
m_rowBuffered = null;
212+
return null;
213+
}
201214
}
202215

203216
var reader = new ByteArrayReader(payload.ArraySegment);

src/MySqlConnector/Serialization/EofPayload.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22

33
namespace MySql.Data.Serialization
44
{
@@ -32,7 +32,7 @@ public static EofPayload Create(PayloadData payload)
3232
public static bool IsEof(PayloadData payload) =>
3333
payload.ArraySegment.Count > 0 && payload.ArraySegment.Count < 9 && payload.ArraySegment.Array[payload.ArraySegment.Offset] == Signature;
3434

35-
private const byte Signature = 0xFE;
35+
public const byte Signature = 0xFE;
3636

3737
private EofPayload(int warningCount, ServerStatus status)
3838
{

src/MySqlConnector/Serialization/HandshakeResponse41Packet.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace MySql.Data.Serialization
1+
namespace MySql.Data.Serialization
22
{
33
internal sealed class HandshakeResponse41Packet
44
{
@@ -20,6 +20,7 @@ private static PayloadWriter CreateCapabilitiesPayload(ProtocolCapabilities serv
2020
(cs.UseAffectedRows ? 0 : ProtocolCapabilities.FoundRows) |
2121
(useCompression ? ProtocolCapabilities.Compress : ProtocolCapabilities.None) |
2222
(serverCapabilities & ProtocolCapabilities.ConnectionAttributes) |
23+
(serverCapabilities & ProtocolCapabilities.DeprecateEof) |
2324
additionalCapabilities));
2425
writer.WriteInt32(0x4000_0000);
2526
writer.WriteByte((byte) CharacterSet.Utf8Mb4Binary);

src/MySqlConnector/Serialization/MySqlSession.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public MySqlSession(ConnectionPool pool, int poolGeneration, int id)
4646
public string DatabaseOverride { get; set; }
4747
public IPAddress IPAddress => (m_tcpClient?.Client.RemoteEndPoint as IPEndPoint)?.Address;
4848
public WeakReference<MySqlConnection> OwningConnection { get; set; }
49+
public bool SupportsDeprecateEof => m_supportsDeprecateEof;
4950

5051
public void ReturnToPool()
5152
{
@@ -236,6 +237,8 @@ public async Task ConnectAsync(ConnectionSettings cs, IOBehavior ioBehavior, Can
236237
if (m_supportsConnectionAttributes && s_connectionAttributes == null)
237238
s_connectionAttributes = CreateConnectionAttributes();
238239

240+
m_supportsDeprecateEof = (initialHandshake.ProtocolCapabilities & ProtocolCapabilities.DeprecateEof) != 0;
241+
239242
var response = HandshakeResponse41Packet.Create(initialHandshake, cs, m_useCompression, m_supportsConnectionAttributes ? s_connectionAttributes : null);
240243
payload = new PayloadData(new ArraySegment<byte>(response));
241244
await SendReplyAsync(payload, ioBehavior, cancellationToken).ConfigureAwait(false);
@@ -896,5 +899,6 @@ private enum State
896899
bool m_useCompression;
897900
bool m_isSecureConnection;
898901
bool m_supportsConnectionAttributes;
902+
bool m_supportsDeprecateEof;
899903
}
900904
}

src/MySqlConnector/Serialization/OkPayload.cs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
namespace MySql.Data.Serialization
1+
using System;
2+
3+
namespace MySql.Data.Serialization
24
{
35
internal sealed class OkPayload
46
{
@@ -9,10 +11,24 @@ internal sealed class OkPayload
911

1012
public const byte Signature = 0x00;
1113

12-
public static OkPayload Create(PayloadData payload)
14+
/* See
15+
* http://web.archive.org/web/20160604101747/http://dev.mysql.com/doc/internals/en/packet-OK_Packet.html
16+
* https://mariadb.com/kb/en/the-mariadb-library/resultset/
17+
* https://github.com/MariaDB/mariadb-connector-j/blob/5fa814ac6e1b4c9cb6d141bd221cbd5fc45c8a78/src/main/java/org/mariadb/jdbc/internal/com/read/resultset/SelectResultSet.java#L443-L444
18+
*/
19+
public static bool IsOk(PayloadData payload, bool deprecateEof) =>
20+
payload.ArraySegment.Array != null && payload.ArraySegment.Count > 0 &&
21+
((payload.ArraySegment.Count > 6 && payload.ArraySegment.Array[payload.ArraySegment.Offset] == Signature) ||
22+
(deprecateEof && payload.ArraySegment.Count < 0xFF_FFFF && payload.ArraySegment.Array[payload.ArraySegment.Offset] == EofPayload.Signature));
23+
24+
public static OkPayload Create(PayloadData payload) => Create(payload, false);
25+
26+
public static OkPayload Create(PayloadData payload, bool deprecateEof)
1327
{
1428
var reader = new ByteArrayReader(payload.ArraySegment);
15-
reader.ReadByte(Signature);
29+
var signature = reader.ReadByte();
30+
if (signature != Signature && (!deprecateEof || signature != EofPayload.Signature))
31+
throw new FormatException("Expected to read 0x00 or 0xFE but got 0x{0:X2}".FormatInvariant(signature));
1632
var affectedRowCount = checked((int) reader.ReadLengthEncodedInteger());
1733
var lastInsertId = checked((long) reader.ReadLengthEncodedInteger());
1834
var serverStatus = (ServerStatus) reader.ReadUInt16();

0 commit comments

Comments
 (0)