Skip to content

Commit ed46175

Browse files
committed
Merge master into net6.
Conflicts: src/MySqlConnector/MySqlConnector.csproj
2 parents c6094dc + c0768e0 commit ed46175

29 files changed

+408
-90
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Async MySQL Connector for .NET and .NET Core
22

3-
This is an [ADO.NET](https://msdn.microsoft.com/en-us/library/e80y5yhx.aspx) data
3+
This is an [ADO.NET](https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/) data
44
provider for [MySQL](https://www.mysql.com/). It provides implementations of
55
`DbConnection`, `DbCommand`, `DbDataReader`, `DbTransaction`—the classes
66
needed to query and update databases from managed code.

azure-pipelines.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ jobs:
204204
unsupportedFeatures: 'Ed25519,CachingSha2Password,Tls11,Tls13,UuidToBin'
205205
'MySQL 8.0':
206206
image: 'mysql:8.0'
207-
unsupportedFeatures: 'Ed25519,Tls11'
207+
unsupportedFeatures: 'Ed25519,Tls11,ZeroDateTime'
208208
'MariaDB 10.2':
209209
image: 'mariadb:10.2'
210210
unsupportedFeatures: 'Ed25519,Json,Sha256Password,CachingSha2Password,RoundDateTime,Tls11,UuidToBin'

docs/content/overview/version-history.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
lastmod: 2021-03-07
2+
lastmod: 2021-04-24
33
date: 2017-03-27
44
menu:
55
main:
@@ -10,6 +10,32 @@ weight: 30
1010

1111
# Version History
1212

13+
### 1.3.7
14+
15+
* Add support for [SingleStore](https://www.singlestore.com/): [#968](https://github.com/mysql-net/MySqlConnector/pull/968).
16+
* Thanks to [Carl Sverre](https://github.com/carlsverre) and [Tigran Avanesov](https://github.com/tavanesov-ua) for contributions to this release.
17+
18+
### 1.3.6
19+
20+
* Add NuGet Package ReadMe: [#978](https://github.com/mysql-net/MySqlConnector/issues/978).
21+
22+
### 1.3.5
23+
24+
* Support `StringBuilder`, `Memory<char>`, and `ReadOnlyMemory<char>` as `MySqlParameter.Value` values: [#975](https://github.com/mysql-net/MySqlConnector/issues/975).
25+
* Fix `ArgumentException` in `MySqlBulkCopy`: [#974](https://github.com/mysql-net/MySqlConnector/issues/974).
26+
27+
### 1.3.4
28+
29+
* Improve compatibility with MySQL Server 8.0.24:
30+
* Ignore new `ER_CLIENT_INTERACTION_TIMEOUT` error packet sent to timed-out connections: [#970](https://github.com/mysql-net/MySqlConnector/issues/970).
31+
* Known Issue: Connections with `UseCompression=true` may throw a `MySqlProtocolException` when timed out.
32+
33+
### 1.3.3
34+
35+
* Support `Enum` parameters in prepared commands: [#965](https://github.com/mysql-net/MySqlConnector/issues/965).
36+
* Fix `OverflowException` reading `OkPayload`: [#966](https://github.com/mysql-net/MySqlConnector/issues/966).
37+
* Fix internal SQL parsing error with C-style comments.
38+
1339
### 1.3.2
1440

1541
* Fix a bug that could cause a timed-out query to still throw a `QueryInterrupted` `MySqlException` instead of `CommandTimeoutExpired`.

docs/content/troubleshooting/parameter-types.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
lastmod: 2021-01-16
2+
lastmod: 2021-04-23
33
date: 2021-01-15
44
title: MySqlParameter Types
55
customtitle: "Type of value supplied to MySqlParameter.Value isn’t supported"
@@ -38,4 +38,5 @@ In some cases, this may be as simple as calling `.ToString()` or `.ToString(Cult
3838
* .NET primitives: `bool`, `byte`, `char`, `double`, `float`, `int`, `long`, `sbyte`, `short`, `uint`, `ulong`, `ushort`
3939
* Common types: `DateTime`, `DateTimeOffset`, `decimal`, `enum`, `Guid`, `string`, `TimeSpan`
4040
* BLOB types: `ArraySegment<byte>`, `byte[]`, `Memory<byte>`, `ReadOnlyMemory<byte>`
41+
* String types: `Memory<char>`, `ReadOnlyMemory<char>`, `StringBuilder`
4142
* Custom MySQL types: `MySqlDateTime`, `MySqlGeometry`

docs/content/tutorials/connect-ssh.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
lastmod: 2019-08-01
2+
lastmod: 2021-04-22
33
date: 2019-07-30
44
menu:
55
main:
@@ -99,10 +99,8 @@ using (sshClient)
9999
Password = databasePassword,
100100
};
101101

102-
using (var connection = new MySqlConnection(csb.ConnectionString))
103-
{
104-
connection.Open();
105-
}
102+
using var connection = new MySqlConnection(csb.ConnectionString);
103+
connection.Open();
106104
}
107105
```
108106

@@ -115,7 +113,7 @@ is reachable from the SSH Server, but not from the client computer), use the fol
115113
var sshServer = "your ssh server";
116114
var sshUserName = "your SSH user name";
117115
var sshPassword = "your SSH password";
118-
var databaseServer = "your ssh server";
116+
var databaseServer = "your database server";
119117
var databaseUserName = "your database user name";
120118
var databasePassword = "your database password";
121119

@@ -130,9 +128,7 @@ using (sshClient)
130128
Password = databasePassword,
131129
};
132130

133-
using (var connection = new MySqlConnection(csb.ConnectionString))
134-
{
135-
connection.Open();
136-
}
131+
using var connection = new MySqlConnection(csb.ConnectionString);
132+
connection.Open();
137133
}
138134
```

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,10 +274,11 @@ The following bugs in Connector/NET are fixed by switching to MySqlConnector. (~
274274
* ~~[#100218](https://bugs.mysql.com/bug.php?id=100218): `TIME(n)` microsecond values deserialized incorrectly with prepared command~~
275275
* ~~[#100306](https://bugs.mysql.com/bug.php?id=100306): `Command.Prepare` sends wrong statement to server~~
276276
* ~~[#100522](https://bugs.mysql.com/bug.php?id=100522): ` MySqlCommand.Parameters.Insert(-1)` succeeds but should fail~~
277-
* [#101252](https://bugs.mysql.com/bug.php?id=101252): Can't query `CHAR(36)` column containing `NULL`
277+
* ~~[#101252](https://bugs.mysql.com/bug.php?id=101252): Can't query `CHAR(36)` column containing `NULL`~~
278278
* [#101253](https://bugs.mysql.com/bug.php?id=101253): Default value for `MySqlParameter.Value` changed from null to `0`
279279
* ~~[#101302](https://bugs.mysql.com/bug.php?id=101302): Stored Procedure `BOOL` parameter can only be mapped to `MySqlDbType.Byte`~~
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
282-
* [#101714](https://bugs.mysql.com/bug.php?id=101714): Extremely slow performance reading result sets
282+
* ~~[#101714](https://bugs.mysql.com/bug.php?id=101714): Extremely slow performance reading result sets~~
283283
* [#102593](https://bugs.mysql.com/bug.php?id=102593): Can't use `MemoryStream` as `MySqlParameter.Value`
284+
* [#103390](https://bugs.mysql.com/bug.php?id=103390): Can't query `CHAR(36)` column if `MySqlCommand` is prepared

src/MySqlConnector/Core/BackgroundConnectionResetHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public static async Task ReturnSessionsAsync()
124124
}
125125
}
126126

127-
internal struct SessionResetTask
127+
internal readonly struct SessionResetTask
128128
{
129129
public SessionResetTask(ServerSession session, Task<bool> resetTask, MySqlConnection? owningConnection)
130130
{

src/MySqlConnector/Core/CachedProcedure.cs

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ internal static List<CachedParameter> ParseParameters(string parametersSql)
154154
return new List<CachedParameter>();
155155

156156
// strip precision specifier containing comma
157-
parametersSql = Regex.Replace(parametersSql, @"(DECIMAL|DEC|FIXED|NUMERIC|FLOAT|DOUBLE PRECISION|DOUBLE|REAL)\s*\(\d+(,\s*\d+)\)", @"$1", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
157+
parametersSql = Regex.Replace(parametersSql, @"(DECIMAL|DEC|FIXED|NUMERIC|FLOAT|DOUBLE PRECISION|DOUBLE|REAL)\s*\([0-9]+(,\s*[0-9]+)\)", @"$1", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
158158

159159
// strip enum values containing commas (these would have been stripped by ParseDataType anyway)
160160
parametersSql = Regex.Replace(parametersSql, @"ENUM\s*\([^)]+\)", "ENUM", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
@@ -194,60 +194,34 @@ internal static List<CachedParameter> ParseParameters(string parametersSql)
194194

195195
internal static string ParseDataType(string sql, out bool unsigned, out int length)
196196
{
197-
if (sql.EndsWith(" ZEROFILL", StringComparison.OrdinalIgnoreCase))
198-
sql = sql.Substring(0, sql.Length - 9);
199-
unsigned = false;
200-
if (sql.EndsWith(" UNSIGNED", StringComparison.OrdinalIgnoreCase))
201-
{
202-
unsigned = true;
203-
sql = sql.Substring(0, sql.Length - 9);
204-
}
205197
sql = Regex.Replace(sql, " (CHARSET|CHARACTER SET) [A-Za-z0-9_]+", "", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
206198
sql = Regex.Replace(sql, " (COLLATE) [A-Za-z0-9_]+", "", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
207199
sql = Regex.Replace(sql, @"ENUM\s*\([^)]+\)", "ENUM", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
208200

209201
length = 0;
210-
var match = Regex.Match(sql, @"\s*\(\s*(\d+)\s*(?:,\s*\d+\s*)?\)");
202+
var match = Regex.Match(sql, @"\s*\(\s*([0-9]+)\s*(?:,\s*[0-9]+\s*)?\)");
211203
if (match.Success)
212204
{
213205
length = int.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
214-
sql = Regex.Replace(sql, @"\s*\(\s*\d+\s*(?:,\s*\d+\s*)?\)", "");
206+
sql = Regex.Replace(sql, @"\s*\(\s*[0-9]+\s*(?:,\s*[0-9]+\s*)?\)", "");
215207
}
216208

217-
sql = sql.Trim();
209+
var list = sql.Trim().Split(new char[] {' '});
210+
var type = string.Empty;
218211

219-
// normalize alternate data type names
220-
if (sql.Equals("BOOL", StringComparison.OrdinalIgnoreCase) || sql.Equals("BOOLEAN", StringComparison.OrdinalIgnoreCase))
221-
{
222-
sql = "TINYINT";
223-
length = 1;
224-
}
225-
else if (sql.Equals("INTEGER", StringComparison.OrdinalIgnoreCase))
226-
{
227-
sql = "INT";
228-
}
229-
else if (sql.Equals("NUMERIC", StringComparison.OrdinalIgnoreCase) || sql.Equals("FIXED", StringComparison.OrdinalIgnoreCase))
230-
{
231-
sql = "DECIMAL";
232-
}
233-
else if (sql.Equals("REAL", StringComparison.OrdinalIgnoreCase) || sql.Equals("DOUBLE PRECISION", StringComparison.OrdinalIgnoreCase))
234-
{
235-
sql = "DOUBLE";
236-
}
237-
else if (sql.Equals("NVARCHAR", StringComparison.OrdinalIgnoreCase) || sql.Equals("CHARACTER VARYING", StringComparison.OrdinalIgnoreCase) || sql.Equals("NATIONAL VARCHAR", StringComparison.OrdinalIgnoreCase))
212+
if (list.Length < 2 || !s_typeMapping.TryGetValue(list[0] + ' ' + list[1], out type))
238213
{
239-
sql = "VARCHAR";
240-
}
241-
else if (sql.Equals("NCHAR", StringComparison.OrdinalIgnoreCase) || sql.Equals("CHARACTER", StringComparison.OrdinalIgnoreCase) || sql.Equals("NATIONAL CHAR", StringComparison.OrdinalIgnoreCase))
242-
{
243-
sql = "CHAR";
244-
}
245-
else if (sql.Equals("CHAR BYTE", StringComparison.OrdinalIgnoreCase))
246-
{
247-
sql = "BINARY";
214+
if (s_typeMapping.TryGetValue(list[0], out type))
215+
{
216+
if (list[0].StartsWith("BOOL", StringComparison.OrdinalIgnoreCase))
217+
{
218+
length = 1;
219+
}
220+
}
248221
}
249222

250-
return sql;
223+
unsigned = list.Contains("UNSIGNED", StringComparer.OrdinalIgnoreCase);
224+
return type ?? list[0];
251225
}
252226

253227
private static CachedParameter CreateCachedParameter(int ordinal, string? direction, string name, string dataType, bool unsigned, int length, string originalSql)
@@ -265,6 +239,23 @@ private static CachedParameter CreateCachedParameter(int ordinal, string? direct
265239
string FullyQualified => $"`{m_schema}`.`{m_component}`";
266240

267241
static readonly IMySqlConnectorLogger Log = MySqlConnectorLogManager.CreateLogger(nameof(CachedProcedure));
242+
static readonly IReadOnlyDictionary<string, string> s_typeMapping = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
243+
{
244+
{ "BOOL", "TINYINT" },
245+
{ "BOOLEAN", "TINYINT" },
246+
{ "INTEGER", "INT" },
247+
{ "NUMERIC", "DECIMAL" },
248+
{ "FIXED", "DECIMAL" },
249+
{ "REAL", "DOUBLE" },
250+
{ "DOUBLE PRECISION", "DOUBLE" },
251+
{ "NVARCHAR", "VARCHAR" },
252+
{ "CHARACTER VARYING", "VARCHAR" },
253+
{ "NATIONAL VARCHAR", "VARCHAR" },
254+
{ "NCHAR", "CHAR" },
255+
{ "CHARACTER", "CHAR" },
256+
{ "NATIONAL CHAR", "CHAR" },
257+
{ "CHAR BYTE", "BINARY" }
258+
};
268259

269260
readonly string m_schema;
270261
readonly string m_component;

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,10 @@ public async Task<bool> TryResetConnectionAsync(ConnectionSettings cs, IOBehavio
584584
{
585585
Log.Debug(ex, "Session{0} ignoring IOException in TryResetConnectionAsync", m_logArguments);
586586
}
587+
catch (MySqlException ex) when (ex.ErrorCode == MySqlErrorCode.ClientInteractionTimeout)
588+
{
589+
Log.Debug(ex, "Session{0} ignoring ClientInteractionTimeout MySqlException in TryResetConnectionAsync", m_logArguments);
590+
}
587591
catch (ObjectDisposedException ex)
588592
{
589593
Log.Debug(ex, "Session{0} ignoring ObjectDisposedException in TryResetConnectionAsync", m_logArguments);
@@ -795,6 +799,10 @@ public async ValueTask<bool> TryPingAsync(bool logInfo, IOBehavior ioBehavior, C
795799
{
796800
Log.Debug(ex, "Session{0} ping failed due to IOException", m_logArguments);
797801
}
802+
catch (MySqlException ex) when (ex.ErrorCode == MySqlErrorCode.ClientInteractionTimeout)
803+
{
804+
Log.Debug(ex, "Session{0} ping failed due to ClientInteractionTimeout MySqlException", m_logArguments);
805+
}
798806
catch (SocketException ex)
799807
{
800808
Log.Debug(ex, "Session{0} ping failed due to SocketException", m_logArguments);
@@ -1584,7 +1592,6 @@ private static void SafeDispose<T>(ref T? disposable)
15841592

15851593
internal void SetFailed(Exception exception)
15861594
{
1587-
m_logArguments[1] = exception.Message;
15881595
Log.Info(exception, "Session{0} setting state to Failed", m_logArguments);
15891596
lock (m_lock)
15901597
m_state = State.Failed;
@@ -1677,7 +1684,10 @@ private Exception CreateExceptionForErrorPayload(ReadOnlySpan<byte> span)
16771684
var errorPayload = ErrorPayload.Create(span);
16781685
if (Log.IsDebugEnabled())
16791686
Log.Debug("Session{0} got error payload: Code={1}, State={2}, Message={3}", m_logArguments[0], errorPayload.ErrorCode, errorPayload.State, errorPayload.Message);
1680-
return errorPayload.ToException();
1687+
var exception = errorPayload.ToException();
1688+
if (exception.ErrorCode is MySqlErrorCode.ClientInteractionTimeout)
1689+
SetFailed(exception);
1690+
return exception;
16811691
}
16821692

16831693
private void ClearPreparedStatements()

src/MySqlConnector/Core/TypeMapper.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ private void AddColumnTypeMetadata(ColumnTypeMetadata columnTypeMetadata)
151151

152152
internal DbTypeMapping? GetDbTypeMapping(Type clrType)
153153
{
154+
#if !NETSTANDARD1_3
155+
if (clrType.IsEnum)
156+
clrType = Enum.GetUnderlyingType(clrType);
157+
#endif
154158
m_dbTypeMappingsByClrType.TryGetValue(clrType, out var dbTypeMapping);
155159
return dbTypeMapping;
156160
}

0 commit comments

Comments
 (0)