Skip to content

Commit

Permalink
Pull 2.2.5-2.2.7 releases
Browse files Browse the repository at this point in the history
Summary:
This diff contains changes that were made in the original connector in 2.2.5-2.2.7 releases:
- Fix parsing nan as float/double value on .NET Framework.
- Ignore deadlock exception when rolling back an XA transaction.
- Work around ephemeral PEM bug on Windows.
- Respect ConnectTimeout when resetting connection.
- Prevent connection pool falling back to an unsupported TLS version.

Also it contains new test that is failing -- ResetConnectionTimeout(). It's commented for now, but will be resolved in the next diff.

Test Plan: https://app.circleci.com/pipelines/github/memsql/SingleStoreNETConnector/305/workflows/21219911-bf42-429e-a689-331c06da44a3

Reviewers: pmishchenko-ua

Reviewed By: pmishchenko-ua

Subscribers: engineering-list

JIRA Issues: PLAT-6674

Differential Revision: https://grizzly.internal.memcompute.com/D64455
  • Loading branch information
okramarenko committed Sep 8, 2023
1 parent f914b57 commit ec495d0
Show file tree
Hide file tree
Showing 26 changed files with 182 additions and 128 deletions.
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ dotnet_diagnostic.CA1032.severity = none # Implement standard exception construc
dotnet_diagnostic.CA1062.severity = silent # Validate arguments of public methods.
dotnet_diagnostic.CA1307.severity = silent # Specify StringComparison for clarity.
dotnet_diagnostic.CA1508.severity = silent # Avoid dead conditional code.
dotnet_diagnostic.CA1510.severity = none # Use ArgumentNullException.ThrowIfNull.
dotnet_diagnostic.CA1513.severity = none # Use ObjectDisposedException.ThrowIf.
dotnet_diagnostic.CA1849.severity = none # Call async methods when in an async method.
dotnet_diagnostic.CA1859.severity = silent # Use concrete return types for performance.
dotnet_diagnostic.CA2000.severity = none # Use recommended Dispose pattern.
dotnet_diagnostic.CA2100.severity = none # Review SQL queries for security vulnerabilities.
dotnet_diagnostic.CA2213.severity = silent # Disposable fields should be disposed.
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

<ItemGroup>
<!-- <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All"/>
<PackageReference Include="MinVer" Version="4.2.0">
<PackageReference Include="MinVer" Version="4.3.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Title>SingleStoreConnector Ed25519 Authentication Plugin</Title>
<Description>Implements the client_ed25519 authentication plugin for SingleStore.</Description>
<Copyright>Copyright 2019–2021 Bradley Grainger</Copyright>
<Copyright>Copyright 2022 SingleStore Inc.</Copyright>
<Copyright>Copyright 2022-2023 SingleStore Inc.</Copyright>
<Authors>Bradley Grainger</Authors>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>singlestore;singlestoreconnector;authentication;ed25519</PackageTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Title>SingleStoreConnector Logging Adapter for Microsoft.Extensions.Logging</Title>
<Description>Writes SingleStoreConnector logging output to Microsoft.Extensions.Logging with one line of code.</Description>
<Copyright>Copyright 2017–2021 Bradley Grainger</Copyright>
<Copyright>Copyright 2022 SingleStore Inc.</Copyright>
<Copyright>Copyright 2022-2023 SingleStore Inc.</Copyright>
<Authors>Bradley Grainger</Authors>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>singlestore;singlestoreconnector;async;ado.net;database;netcore;logging</PackageTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Title>SingleStoreConnector Logging Adapter for NLog</Title>
<Description>Writes lightly-structured SingleStoreConnector logging output to NLog.</Description>
<Copyright>Copyright 2018–2021 Bradley Grainger</Copyright>
<Copyright>Copyright 2022 SingleStore Inc.</Copyright>
<Copyright>Copyright 2022-2023 SingleStore Inc.</Copyright>
<Authors>Rolf Kristensen</Authors>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>singlestore;singlestoreconnector;async;ado.net;database;netcore;NLog;logging</PackageTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Title>SingleStoreConnector Logging Adapter for Serilog</Title>
<Description>Writes lightly-structured SingleStoreConnector logging output to Serilog.</Description>
<Copyright>Copyright 2017–2021 Bradley Grainger</Copyright>
<Copyright>Copyright 2022 SingleStore Inc.</Copyright>
<Copyright>Copyright 2022-2023 SingleStore Inc.</Copyright>
<Authors>Marc Lewandowski</Authors>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>singlestore;singlestoreconnector;async;ado.net;database;netcore;serilog;logging</PackageTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<Title>SingleStoreConnector Logging Adapter for log4net</Title>
<Description>Writes SingleStoreConnector logging output to log4net with one line of code.</Description>
<Copyright>Copyright 2017–2021 Bradley Grainger</Copyright>
<Copyright>Copyright 2022 SingleStore Inc.</Copyright>
<Copyright>Copyright 2022-2023 SingleStore Inc.</Copyright>
<Authors>Bradley Grainger</Authors>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>singlestore;singlestoreconnector;async;ado.net;database;netcore;log4net;logging</PackageTags>
Expand Down
9 changes: 8 additions & 1 deletion src/SingleStoreConnector/Core/ConnectionPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal sealed class ConnectionPool : IDisposable

public SslProtocols SslProtocols { get; set; }

public async ValueTask<ServerSession> GetSessionAsync(SingleStoreConnection connection, int startTickCount, Activity? activity, IOBehavior ioBehavior, CancellationToken cancellationToken)
public async ValueTask<ServerSession> GetSessionAsync(SingleStoreConnection connection, int startTickCount, int timeoutMilliseconds, Activity? activity, IOBehavior ioBehavior, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();

Expand Down Expand Up @@ -65,9 +65,16 @@ public async ValueTask<ServerSession> GetSessionAsync(SingleStoreConnection conn
else
{
if (ConnectionSettings.ConnectionReset || session.DatabaseOverride is not null)
{
if (timeoutMilliseconds != 0)
session.SetTimeout(Math.Max(1, timeoutMilliseconds - (Environment.TickCount - startTickCount)));
reuseSession = await session.TryResetConnectionAsync(ConnectionSettings, connection, ioBehavior, cancellationToken).ConfigureAwait(false);
session.SetTimeout(Constants.InfiniteTimeout);
}
else
{
reuseSession = true;
}
}

if (!reuseSession)
Expand Down
26 changes: 17 additions & 9 deletions src/SingleStoreConnector/Core/ServerSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -448,14 +448,15 @@ public async Task DisposeAsync(IOBehavior ioBehavior, CancellationToken cancella
// (which is SslProtocols.None; see https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls),
// then fall back to SslProtocols.Tls11 if that fails and it's possible that the cause is a yaSSL server.
bool shouldRetrySsl;
var shouldUpdatePoolSslProtocols = false;
var sslProtocols = Pool?.SslProtocols ?? cs.TlsVersions;
PayloadData payload;
InitialHandshakePayload initialHandshake;
do
{
bool tls11or10Supported = (sslProtocols & (SslProtocols.Tls | SslProtocols.Tls11)) != SslProtocols.None;
bool tls12Supported = (sslProtocols & SslProtocols.Tls12) == SslProtocols.Tls12;
shouldRetrySsl = (sslProtocols == SslProtocols.None || (tls12Supported && tls11or10Supported)) && Utility.IsWindows();
var isTls11or10Supported = (sslProtocols & (SslProtocols.Tls | SslProtocols.Tls11)) != SslProtocols.None;
var isTls12Supported = (sslProtocols & SslProtocols.Tls12) == SslProtocols.Tls12;
shouldRetrySsl = (sslProtocols == SslProtocols.None || (isTls12Supported && isTls11or10Supported)) && Utility.IsWindows();

var connected = false;
if (cs.ConnectionProtocol == SingleStoreConnectionProtocol.Sockets)
Expand Down Expand Up @@ -538,19 +539,20 @@ public async Task DisposeAsync(IOBehavior ioBehavior, CancellationToken cancella
{
await InitSslAsync(initialHandshake.ProtocolCapabilities, cs, connection, sslProtocols, ioBehavior, cancellationToken).ConfigureAwait(false);
shouldRetrySsl = false;
if (shouldUpdatePoolSslProtocols && Pool is not null)
Pool.SslProtocols = sslProtocols;
}
catch (ArgumentException ex) when (ex.ParamName == "sslProtocolType" && sslProtocols == SslProtocols.None)
{
Log.Debug(ex, "Session{0} doesn't support SslProtocols.None; falling back to explicitly specifying SslProtocols", m_logArguments);
sslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
}
catch (Exception ex) when (shouldRetrySsl && ((ex is SingleStoreException && ex.InnerException is IOException) || ex is IOException))
catch (Exception ex) when (shouldRetrySsl && ((ex is SingleStoreException && ex.InnerException is AuthenticationException or IOException) || ex is AuthenticationException or IOException))
{
// negotiating TLS 1.2 with a yaSSL-based server throws an exception on Windows, see comment at top of method
Log.Debug(ex, "Session{0} failed negotiating TLS; falling back to TLS 1.1", m_logArguments);
Log.Warn(ex, "Session{0} failed negotiating TLS; falling back to TLS 1.1", m_logArguments);
sslProtocols = sslProtocols == SslProtocols.None ? SslProtocols.Tls | SslProtocols.Tls11 : (SslProtocols.Tls | SslProtocols.Tls11) & sslProtocols;
if (Pool is not null)
Pool.SslProtocols = sslProtocols;
shouldUpdatePoolSslProtocols = true;
}
}
else
Expand Down Expand Up @@ -1586,6 +1588,14 @@ X509CertificateCollection LoadCertificate(string sslKeyFile, string sslCertifica
throw new NotSupportedException("SslCert and SslKey connection string options are not supported in netstandard2.0.");
#elif NET5_0_OR_GREATER
m_clientCertificate = X509Certificate2.CreateFromPemFile(sslCertificateFile, sslKeyFile);
if (Utility.IsWindows())
{
// Schannel has a bug where ephemeral keys can't be loaded: https://github.com/dotnet/runtime/issues/23749#issuecomment-485947319
// The workaround is to export the key (which may make it "Perphemeral"): https://github.com/dotnet/runtime/issues/23749#issuecomment-739895373
var oldCertificate = m_clientCertificate;
m_clientCertificate = new X509Certificate2(m_clientCertificate.Export(X509ContentType.Pkcs12));
oldCertificate.Dispose();
}
return new() { m_clientCertificate };
#else
m_logArguments[1] = sslKeyFile;
Expand Down Expand Up @@ -1617,7 +1627,6 @@ X509CertificateCollection LoadCertificate(string sslKeyFile, string sslCertifica
RSA rsa;
try
{
#pragma warning disable CA1416
// SslStream on Windows needs a KeyContainerName to be set
var csp = new CspParameters
{
Expand All @@ -1627,7 +1636,6 @@ X509CertificateCollection LoadCertificate(string sslKeyFile, string sslCertifica
{
PersistKeyInCsp = true,
};
#pragma warning restore
}
catch (PlatformNotSupportedException)
{
Expand Down
6 changes: 3 additions & 3 deletions src/SingleStoreConnector/Core/ServerVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ public ServerVersion(ReadOnlySpan<byte> versionString)
if (Utf8Parser.TryParse(versionString, out int major, out var bytesConsumed))
{
versionString = versionString[bytesConsumed..];
if (versionString is [0x2E, ..])
if (versionString is [0x2E, .. ])
{
versionString = versionString[1..];
if (Utf8Parser.TryParse(versionString, out minor, out bytesConsumed))
{
versionString = versionString[bytesConsumed..];
if (versionString is [0x2E, ..])
if (versionString is [0x2E, .. ])
{
versionString = versionString[1..];
if (Utf8Parser.TryParse(versionString, out build, out bytesConsumed))
Expand All @@ -36,7 +36,7 @@ public ServerVersion(ReadOnlySpan<byte> versionString)
Version = new Version(major, minor, build);

// check for MariaDB version appended to a fake MySQL version
if (versionString is [0x2D, ..])
if (versionString is [ 0x2D, .. ])
{
versionString = versionString[1..];
ReadOnlySpan<byte> mariaDb = "-MariaDB"u8;
Expand Down
8 changes: 6 additions & 2 deletions src/SingleStoreConnector/Core/TextRow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,21 +108,25 @@ protected override object GetValueCore(ReadOnlySpan<byte> data, ColumnDefinition
case ColumnType.Float:
if (Utf8Parser.TryParse(data, out float floatValue, out var floatBytesConsumed) && floatBytesConsumed == data.Length)
return floatValue;
ReadOnlySpan<byte> floatInfinity = new byte[] { 0x2D, 0x69, 0x6E, 0x66 }; // "-inf"
ReadOnlySpan<byte> floatInfinity = "-inf"u8;
if (data.SequenceEqual(floatInfinity))
return float.NegativeInfinity;
if (data.SequenceEqual(floatInfinity.Slice(1)))
return float.PositiveInfinity;
if (data.SequenceEqual("nan"u8))
return float.NaN;
throw new FormatException($"Couldn't parse value as float: {Encoding.UTF8.GetString(data)}");

case ColumnType.Double:
if (Utf8Parser.TryParse(data, out double doubleValue, out var doubleBytesConsumed) && doubleBytesConsumed == data.Length)
return doubleValue;
ReadOnlySpan<byte> doubleInfinity = new byte[] { 0x2D, 0x69, 0x6E, 0x66 }; // "-inf"
ReadOnlySpan<byte> doubleInfinity = "-inf"u8;
if (data.SequenceEqual(doubleInfinity))
return double.NegativeInfinity;
if (data.SequenceEqual(doubleInfinity.Slice(1)))
return double.PositiveInfinity;
if (data.SequenceEqual("nan"u8))
return float.NaN;
throw new FormatException($"Couldn't parse value as double: {Encoding.UTF8.GetString(data)}");

case ColumnType.Decimal:
Expand Down
1 change: 1 addition & 0 deletions src/SingleStoreConnector/Core/TypeMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ private TypeMapper()
var typeDouble = AddDbTypeMapping(new(typeof(double), new[] { DbType.Double }, convert: static o => Convert.ToDouble(o, CultureInfo.InvariantCulture)));
var typeFloat = AddDbTypeMapping(new(typeof(float), new[] { DbType.Single }, convert: static o => Convert.ToSingle(o, CultureInfo.InvariantCulture)));
AddColumnTypeMetadata(new("DECIMAL", typeDecimal, SingleStoreDbType.NewDecimal, createFormat: "DECIMAL({0},{1});precision,scale"));
AddColumnTypeMetadata(new("DECIMAL", typeDecimal, SingleStoreDbType.NewDecimal, isUnsigned: true, createFormat: "DECIMAL({0},{1}) UNSIGNED;precision,scale"));
AddColumnTypeMetadata(new("DECIMAL", typeDecimal, SingleStoreDbType.Decimal));
AddColumnTypeMetadata(new("DOUBLE", typeDouble, SingleStoreDbType.Double));
AddColumnTypeMetadata(new("FLOAT", typeFloat, SingleStoreDbType.Float));
Expand Down
11 changes: 9 additions & 2 deletions src/SingleStoreConnector/Core/XaEnlistedTransaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,15 @@ protected override void OnCommit(Enlistment enlistment)

protected override void OnRollback(Enlistment enlistment)
{
ExecuteXaCommand("END");
ExecuteXaCommand("ROLLBACK");
try
{
ExecuteXaCommand("END");
ExecuteXaCommand("ROLLBACK");
}
catch (SingleStoreException ex) when (ex.ErrorCode is SingleStoreErrorCode.XARBDeadlock)
{
// ignore deadlock when rolling back
}
}

private void ExecuteXaCommand(string statement)
Expand Down
32 changes: 32 additions & 0 deletions src/SingleStoreConnector/Shims/DbColumn.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#if NET461
#pragma warning disable CA1716 // Don't use reserved language keywords
namespace System.Data.Common;

public abstract class DbColumn
{
public bool? AllowDBNull { get; protected set; }
public string? BaseCatalogName { get; protected set; }
public string? BaseColumnName { get; protected set; }
public string? BaseSchemaName { get; protected set; }
public string? BaseServerName { get; protected set; }
public string? BaseTableName { get; protected set; }
public string ColumnName { get; protected set; } = "";
public int? ColumnOrdinal { get; protected set; }
public int? ColumnSize { get; protected set; }
public bool? IsAliased { get; protected set; }
public bool? IsAutoIncrement { get; protected set; }
public bool? IsExpression { get; protected set; }
public bool? IsHidden { get; protected set; }
public bool? IsIdentity { get; protected set; }
public bool? IsKey { get; protected set; }
public bool? IsLong { get; protected set; }
public bool? IsReadOnly { get; protected set; }
public bool? IsUnique { get; protected set; }
public int? NumericPrecision { get; protected set; }
public int? NumericScale { get; protected set; }
public string? UdtAssemblyQualifiedName { get; protected set; }
public Type? DataType { get; protected set; }
public string? DataTypeName { get; protected set; }
public virtual object? this[string property] => null;
}
#endif
2 changes: 1 addition & 1 deletion src/SingleStoreConnector/SingleStoreConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -928,7 +928,7 @@ private async ValueTask<ServerSession> CreateSessionAsync(ConnectionPool? pool,
if (pool is not null)
{
// this returns an open session
return await pool.GetSessionAsync(this, startTickCount, activity, actualIOBehavior, connectToken).ConfigureAwait(false);
return await pool.GetSessionAsync(this, startTickCount, connectionSettings.ConnectionTimeoutMilliseconds, activity, actualIOBehavior, connectToken).ConfigureAwait(false);
}
else
{
Expand Down
3 changes: 2 additions & 1 deletion src/SingleStoreConnector/SingleStoreConnector.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFrameworks>net461;net471;netstandard2.0;netstandard2.1;netcoreapp3.1;net6.0;net7.0</TargetFrameworks>
<Description>A truly async SingleStore ADO.NET provider.</Description>
<Copyright>Copyright 2016–2021 Bradley Grainger</Copyright>
<Copyright>Copyright 2022 SingleStore Inc.</Copyright>
<Copyright>Copyright 2022-2023 SingleStore Inc.</Copyright>
<Authors>SingleStore Inc.</Authors>
<AssemblyName>SingleStoreConnector</AssemblyName>
<PackageId>SingleStoreConnector</PackageId>
Expand Down Expand Up @@ -45,3 +45,4 @@
</ItemGroup>

</Project>

Loading

0 comments on commit ec495d0

Please sign in to comment.