Skip to content

Commit 0589e29

Browse files
committed
Support MemoryStream as parameter value. Fixes #943
1 parent 9f94ab4 commit 0589e29

File tree

4 files changed

+46
-1
lines changed

4 files changed

+46
-1
lines changed

docs/content/tutorials/migrating-from-connector-net.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,4 @@ The following bugs in Connector/NET are fixed by switching to MySqlConnector. (~
280280
* [#101485](https://bugs.mysql.com/bug.php?id=101485): Stored Procedure `JSON` parameter throws “Unhandled type encountered” `MySqlException`
281281
* [#101507](https://bugs.mysql.com/bug.php?id=101507): `MySqlCommand.Cancel` throws `NullReferenceException` for a closed connection
282282
* [#101714](https://bugs.mysql.com/bug.php?id=101714): Extremely slow performance reading result sets
283+
* [#102593](https://bugs.mysql.com/bug.php?id=102593): Can't use `MemoryStream` as `MySqlParameter.Value`

src/MySqlConnector/MySqlParameter.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Data.Common;
55
using System.Diagnostics;
66
using System.Diagnostics.CodeAnalysis;
7+
using System.IO;
78
using MySqlConnector.Core;
89
using MySqlConnector.Protocol.Serialization;
910
using MySqlConnector.Utilities;
@@ -279,14 +280,15 @@ internal void AppendSqlString(ByteBufferWriter writer, StatementPreparerOptions
279280
{
280281
writer.WriteString(ulongValue);
281282
}
282-
else if (Value is byte[] or ReadOnlyMemory<byte> or Memory<byte> or ArraySegment<byte> or MySqlGeometry)
283+
else if (Value is byte[] or ReadOnlyMemory<byte> or Memory<byte> or ArraySegment<byte> or MySqlGeometry or MemoryStream)
283284
{
284285
var inputSpan = Value switch
285286
{
286287
byte[] byteArray => byteArray.AsSpan(),
287288
ArraySegment<byte> arraySegment => arraySegment.AsSpan(),
288289
Memory<byte> memory => memory.Span,
289290
MySqlGeometry geometry => geometry.ValueSpan,
291+
MemoryStream memoryStream => memoryStream.TryGetBuffer(out var streamBuffer) ? streamBuffer.AsSpan() : memoryStream.ToArray().AsSpan(),
290292
_ => ((ReadOnlyMemory<byte>) Value).Span,
291293
};
292294

@@ -509,6 +511,13 @@ internal void AppendBinary(ByteBufferWriter writer, StatementPreparerOptions opt
509511
writer.WriteLengthEncodedInteger(unchecked((ulong) geometry.ValueSpan.Length));
510512
writer.Write(geometry.ValueSpan);
511513
}
514+
else if (Value is MemoryStream memoryStream)
515+
{
516+
if (!memoryStream.TryGetBuffer(out var streamBuffer))
517+
streamBuffer = new ArraySegment<byte>(memoryStream.ToArray());
518+
writer.WriteLengthEncodedInteger(unchecked((ulong) streamBuffer.Count));
519+
writer.Write(streamBuffer);
520+
}
512521
else if (Value is float floatValue)
513522
{
514523
writer.Write(BitConverter.GetBytes(floatValue));

tests/MySqlConnector.Tests/StatementPreparerTests.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Globalization;
4+
using System.IO;
45
using System.Text;
56
using MySqlConnector.Core;
67
using MySqlConnector.Protocol.Serialization;
@@ -172,6 +173,9 @@ public void FormatParameter(object parameterValue, string replacedValue, bool no
172173
new object[] { new TimeSpan(2, 3, 4, 5, 6), "time '51:04:05.006000'" },
173174
new object[] { new TimeSpan(-2, -3, -4, -5, -6), "time '-51:04:05.006000'" },
174175
new object[] { new Guid("00112233-4455-6677-8899-AABBCCDDEEFF"), "'00112233-4455-6677-8899-aabbccddeeff'" },
176+
new object[] { new byte[] { 0x41, 0x42, 0x27, 0x61 }, "_binary'AB\\'a'" },
177+
new object[] { new MemoryStream(new byte[] { 0x41, 0x42, 0x27, 0x61 }), "_binary'AB\\'a'" },
178+
new object[] { new MemoryStream(new byte[] { 0, 0x41, 0x42, 0x27, 0x61, 0x62 }, 1, 4, false, true), "_binary'AB\\'a'" },
175179
};
176180

177181
[Theory]

tests/SideBySide/InsertTests.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Data;
4+
using System.IO;
45
using System.Linq;
56
using System.Threading.Tasks;
67
using Dapper;
@@ -217,6 +218,36 @@ public void InsertMySqlDateTime()
217218
Assert.Equal(new DateTime(2018, 6, 9, 12, 34, 56, 123).AddTicks(4560), datetime);
218219
}
219220

221+
[SkippableTheory(Baseline = "https://bugs.mysql.com/bug.php?id=102593")]
222+
[InlineData(false)]
223+
[InlineData(true)]
224+
public void InsertMemoryStream(bool prepare)
225+
{
226+
m_database.Connection.Execute(@"drop table if exists insert_stream;
227+
create table insert_stream(rowid integer not null primary key auto_increment, str text, blb blob);");
228+
229+
m_database.Connection.Open();
230+
try
231+
{
232+
using var cmd = m_database.Connection.CreateCommand();
233+
cmd.CommandText = @"insert into insert_stream(str, blb) values(@str, @blb);";
234+
cmd.Parameters.AddWithValue("@str", new MemoryStream(new byte[] { 97, 98, 99, 100 }));
235+
cmd.Parameters.AddWithValue("@blb", new MemoryStream(new byte[] { 97, 98, 99, 100 }, 0, 4, false, true));
236+
if (prepare)
237+
cmd.Prepare();
238+
cmd.ExecuteNonQuery();
239+
}
240+
finally
241+
{
242+
m_database.Connection.Close();
243+
}
244+
245+
using var reader = m_database.Connection.ExecuteReader(@"select str, blb from insert_stream order by rowid;");
246+
Assert.True(reader.Read());
247+
Assert.Equal("abcd", reader.GetValue(0));
248+
Assert.Equal(new byte[] { 97, 98, 99, 100 }, reader.GetValue(1));
249+
}
250+
220251
[Fact]
221252
public void InsertOldGuid()
222253
{

0 commit comments

Comments
 (0)