Skip to content

Commit

Permalink
Support MemoryStream as parameter value. Fixes #943
Browse files Browse the repository at this point in the history
  • Loading branch information
bgrainger committed Feb 14, 2021
1 parent 9f94ab4 commit 0589e29
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/content/tutorials/migrating-from-connector-net.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,4 @@ The following bugs in Connector/NET are fixed by switching to MySqlConnector. (~
* [#101485](https://bugs.mysql.com/bug.php?id=101485): Stored Procedure `JSON` parameter throws “Unhandled type encountered” `MySqlException`
* [#101507](https://bugs.mysql.com/bug.php?id=101507): `MySqlCommand.Cancel` throws `NullReferenceException` for a closed connection
* [#101714](https://bugs.mysql.com/bug.php?id=101714): Extremely slow performance reading result sets
* [#102593](https://bugs.mysql.com/bug.php?id=102593): Can't use `MemoryStream` as `MySqlParameter.Value`
11 changes: 10 additions & 1 deletion src/MySqlConnector/MySqlParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Data.Common;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using MySqlConnector.Core;
using MySqlConnector.Protocol.Serialization;
using MySqlConnector.Utilities;
Expand Down Expand Up @@ -279,14 +280,15 @@ internal void AppendSqlString(ByteBufferWriter writer, StatementPreparerOptions
{
writer.WriteString(ulongValue);
}
else if (Value is byte[] or ReadOnlyMemory<byte> or Memory<byte> or ArraySegment<byte> or MySqlGeometry)
else if (Value is byte[] or ReadOnlyMemory<byte> or Memory<byte> or ArraySegment<byte> or MySqlGeometry or MemoryStream)
{
var inputSpan = Value switch
{
byte[] byteArray => byteArray.AsSpan(),
ArraySegment<byte> arraySegment => arraySegment.AsSpan(),
Memory<byte> memory => memory.Span,
MySqlGeometry geometry => geometry.ValueSpan,
MemoryStream memoryStream => memoryStream.TryGetBuffer(out var streamBuffer) ? streamBuffer.AsSpan() : memoryStream.ToArray().AsSpan(),
_ => ((ReadOnlyMemory<byte>) Value).Span,
};

Expand Down Expand Up @@ -509,6 +511,13 @@ internal void AppendBinary(ByteBufferWriter writer, StatementPreparerOptions opt
writer.WriteLengthEncodedInteger(unchecked((ulong) geometry.ValueSpan.Length));
writer.Write(geometry.ValueSpan);
}
else if (Value is MemoryStream memoryStream)
{
if (!memoryStream.TryGetBuffer(out var streamBuffer))
streamBuffer = new ArraySegment<byte>(memoryStream.ToArray());
writer.WriteLengthEncodedInteger(unchecked((ulong) streamBuffer.Count));
writer.Write(streamBuffer);
}
else if (Value is float floatValue)
{
writer.Write(BitConverter.GetBytes(floatValue));
Expand Down
4 changes: 4 additions & 0 deletions tests/MySqlConnector.Tests/StatementPreparerTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using MySqlConnector.Core;
using MySqlConnector.Protocol.Serialization;
Expand Down Expand Up @@ -172,6 +173,9 @@ public void FormatParameter(object parameterValue, string replacedValue, bool no
new object[] { new TimeSpan(2, 3, 4, 5, 6), "time '51:04:05.006000'" },
new object[] { new TimeSpan(-2, -3, -4, -5, -6), "time '-51:04:05.006000'" },
new object[] { new Guid("00112233-4455-6677-8899-AABBCCDDEEFF"), "'00112233-4455-6677-8899-aabbccddeeff'" },
new object[] { new byte[] { 0x41, 0x42, 0x27, 0x61 }, "_binary'AB\\'a'" },
new object[] { new MemoryStream(new byte[] { 0x41, 0x42, 0x27, 0x61 }), "_binary'AB\\'a'" },
new object[] { new MemoryStream(new byte[] { 0, 0x41, 0x42, 0x27, 0x61, 0x62 }, 1, 4, false, true), "_binary'AB\\'a'" },
};

[Theory]
Expand Down
31 changes: 31 additions & 0 deletions tests/SideBySide/InsertTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Dapper;
Expand Down Expand Up @@ -217,6 +218,36 @@ public void InsertMySqlDateTime()
Assert.Equal(new DateTime(2018, 6, 9, 12, 34, 56, 123).AddTicks(4560), datetime);
}

[SkippableTheory(Baseline = "https://bugs.mysql.com/bug.php?id=102593")]
[InlineData(false)]
[InlineData(true)]
public void InsertMemoryStream(bool prepare)
{
m_database.Connection.Execute(@"drop table if exists insert_stream;
create table insert_stream(rowid integer not null primary key auto_increment, str text, blb blob);");

m_database.Connection.Open();
try
{
using var cmd = m_database.Connection.CreateCommand();
cmd.CommandText = @"insert into insert_stream(str, blb) values(@str, @blb);";
cmd.Parameters.AddWithValue("@str", new MemoryStream(new byte[] { 97, 98, 99, 100 }));
cmd.Parameters.AddWithValue("@blb", new MemoryStream(new byte[] { 97, 98, 99, 100 }, 0, 4, false, true));
if (prepare)
cmd.Prepare();
cmd.ExecuteNonQuery();
}
finally
{
m_database.Connection.Close();
}

using var reader = m_database.Connection.ExecuteReader(@"select str, blb from insert_stream order by rowid;");
Assert.True(reader.Read());
Assert.Equal("abcd", reader.GetValue(0));
Assert.Equal(new byte[] { 97, 98, 99, 100 }, reader.GetValue(1));
}

[Fact]
public void InsertOldGuid()
{
Expand Down

0 comments on commit 0589e29

Please sign in to comment.